Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(eks): cluster built with clusterLogging property set prevents the cluster from being modified #21362

Closed
wants to merge 0 commits into from

Conversation

watany-dev
Copy link
Contributor

@watany-dev watany-dev commented Jul 28, 2022

fixed: #20779

The original issue was that in update-cluster-config, updates.updateLogging and updates.updateAccess were not separated and were state dependent.
We reviewed the logic in the conditional branch and decided to make a decision for each state.

As a point of interest for this repair, we picked out the case where updateClusterConfigRequest is updates.updateLogging && updates.updateAccess, and used unittest and We have not added integtest because it seems that the existing integtest is sufficient to verify that the existing behavior is as before.
I would be very glad to get advice on this, as I have a little trouble coming up with a perspective to check if it is necessary.


All Submissions:

Adding new Unconventional Dependencies:

  • This PR adds new unconventional dependencies following the process described here

New Features

  • Have you added the new feature to an integration test?
    • Did you use yarn integ to deploy the infrastructure and generate the snapshot (i.e. yarn integ without --dry-run)?

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license

@gitpod-io
Copy link

gitpod-io bot commented Jul 28, 2022

@aws-cdk-automation aws-cdk-automation requested a review from a team July 28, 2022 15:39
@github-actions github-actions bot added the p2 label Jul 28, 2022
Copy link
Contributor

@TheRealAmazonKendra TheRealAmazonKendra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please make sure that your PR title confirms to the conventional commit standard (fix, feat, chore) and that it is written in a style that will reflect correctly in the change log.

Additionally, please make sure that your PR body describes the problem the PR is solving, and the design approach and alternatives considered. Explain why the PR solves the problem. A link to an issue is helpful, but does not replace an explanation of your thought process (See Contributing Guide, Pull Requests)

@TheRealAmazonKendra
Copy link
Contributor

I think we also need some integration tests for this fix.

@watany-dev watany-dev changed the title fix: EKS cluster_logging property makes cluster unmanageable fix(eks): EKS cluster_logging property makes cluster unmanageable Jul 28, 2022
@watany-dev
Copy link
Contributor Author

Thank you. I will challenge the INTEGRATION TESTS and take this issue in a better direction.

@TheRealAmazonKendra TheRealAmazonKendra changed the title fix(eks): EKS cluster_logging property makes cluster unmanageable fix(eks): cluster_logging property makes cluster unmanageable Jul 28, 2022
@@ -137,10 +137,17 @@ export class ClusterResourceHandler extends ResourceHandler {
}

if (updates.updateLogging || updates.updateAccess) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@watany-dev an error should be thrown when updates.updateLogging and updates.updateAccess are both true, as updating both logging configuration and resources vpc configuration results in an error from the EKS API (even though it is not documented in EKS UpdateClusterConfig API)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems I did not know the correct specifications. I will try to re-write it again with that useful information. Thanks.

@mergify mergify bot dismissed TheRealAmazonKendra’s stale review August 3, 2022 10:50

Pull request has been modified.

@TheRealAmazonKendra TheRealAmazonKendra changed the title fix(eks): cluster_logging property makes cluster unmanageable fix(eks): cluster built with cluster_logging property set prevents the cluster from being modified Aug 3, 2022
Copy link
Contributor

@TheRealAmazonKendra TheRealAmazonKendra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall this needs more testing. I've already mentioned integration tests, I think, but this also needs a bit more unit testing coverage for the change. If it's actually already covered but is just not showing up in this PR because you didn't make changes to it, please just link it and I'll take a look to ensure I think it's enough.

});
Template.fromStack(stack);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is no longer testing anything.

@@ -136,23 +136,33 @@ export class ClusterResourceHandler extends ResourceHandler {
return this.updateClusterVersion(this.newProps.version);
}

if (updates.updateLogging || updates.updateAccess) {
//error should be thrown when updates.updateLogging and updates.updateAccess are both true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
//error should be thrown when updates.updateLogging and updates.updateAccess are both true
// Error should be thrown when updates.updateLogging and updates.updateAccess are both true

if (updates.updateLogging || updates.updateAccess) {
//error should be thrown when updates.updateLogging and updates.updateAccess are both true
if (updates.updateLogging && updates.updateAccess) {
throw new Error('Cannot update cluster updateLogging and updateAccess are both true');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
throw new Error('Cannot update cluster updateLogging and updateAccess are both true');
throw new Error('updateLogging and updateAccess cannot both be set to true');

});


Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

Copy link
Contributor

@TheRealAmazonKendra TheRealAmazonKendra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, I've just done a deeper dive into the code and I don't think this is the right path forward. I think that we shouldn't throw an error if both are true and, instead, do one update and then the other in succession.

@TheRealAmazonKendra TheRealAmazonKendra changed the title fix(eks): cluster built with cluster_logging property set prevents the cluster from being modified fix(eks): cluster built with clusterLogging property set prevents the cluster from being modified Aug 3, 2022
@watany-dev
Copy link
Contributor Author

watany-dev commented Aug 4, 2022

Thanks for your comment. I will re-implement this policy.

if both are true and, instead, do one update and then the other in succession.

I am embarrassed to ask this because it is an elementary question.
I am having trouble getting .updateClusterConfig to return as a single value when I run it twice and return it as a single return, as in the sample below.
When I try to merge updateResponse1 and updateResponse2 in the example below, the updateLogging result is overwritten by the updateAccess result. (i.e., Logging is empty).

    if (updates.updateLogging) {
      const config: aws.EKS.UpdateClusterConfigRequest = {
        name: this.clusterName,
        logging: this.newProps.logging,
      };
      if (!updates.updateAccess) {
        const updateResponse1: aws.EKS.UpdateClusterConfigResponse = await this.eks.updateClusterConfig(config);
        return { EksUpdateId: updateResponse1.update?.id };
      }

      const config2: aws.EKS.UpdateClusterConfigRequest = {
        name: this.clusterName,
      };
      config2.resourcesVpcConfig = {
        endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess,
        endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess,
        publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs,
      };

      const updateResponse1 = await this.eks.updateClusterConfig(config);
      const updateResponse2 = await this.eks.updateClusterConfig(config2);
      const updateResponse = { ...updateResponse1, ...updateResponse2 };
      // some deep copy?
      return { EksUpdateId: (updateResponse.update?.id) };
    }

@yakireliyahu1987
Copy link

Thanks for your comment. I will re-implement this policy.

if both are true and, instead, do one update and then the other in succession.

I am embarrassed to ask this because it is an elementary question. I am having trouble getting .updateClusterConfig to return as a single value when I run it twice and return it as a single return, as in the sample below. When I try to merge updateResponse1 and updateResponse2 in the example below, the updateLogging result is overwritten by the updateAccess result. (i.e., Logging is empty).

    if (updates.updateLogging) {
      const config: aws.EKS.UpdateClusterConfigRequest = {
        name: this.clusterName,
        logging: this.newProps.logging,
      };
      if (!updates.updateAccess) {
        const updateResponse1: aws.EKS.UpdateClusterConfigResponse = await this.eks.updateClusterConfig(config);
        return { EksUpdateId: updateResponse1.update?.id };
      }

      const config2: aws.EKS.UpdateClusterConfigRequest = {
        name: this.clusterName,
      };
      config2.resourcesVpcConfig = {
        endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess,
        endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess,
        publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs,
      };

      const updateResponse1 = await this.eks.updateClusterConfig(config);
      const updateResponse2 = await this.eks.updateClusterConfig(config2);
      const updateResponse = { ...updateResponse1, ...updateResponse2 };
      // some deep copy?
      return { EksUpdateId: (updateResponse.update?.id) };
    }

@watany-dev I'm not sure the suggested logic will work (even before merging the responses, which has its own issues), as when you update the cluster configuration in the first command, it transitions to an "Updating" state, and will reject any further requests until that operation is done, and the cluster is back to an "Active" state. You should have some waiting logic that ensures the cluster has applied the first update before continuing to the next operation.

@TheRealAmazonKendra
Copy link
Contributor

Thanks for your comment. I will re-implement this policy.

if both are true and, instead, do one update and then the other in succession.

I am embarrassed to ask this because it is an elementary question. I am having trouble getting .updateClusterConfig to return as a single value when I run it twice and return it as a single return, as in the sample below. When I try to merge updateResponse1 and updateResponse2 in the example below, the updateLogging result is overwritten by the updateAccess result. (i.e., Logging is empty).

    if (updates.updateLogging) {
      const config: aws.EKS.UpdateClusterConfigRequest = {
        name: this.clusterName,
        logging: this.newProps.logging,
      };
      if (!updates.updateAccess) {
        const updateResponse1: aws.EKS.UpdateClusterConfigResponse = await this.eks.updateClusterConfig(config);
        return { EksUpdateId: updateResponse1.update?.id };
      }

      const config2: aws.EKS.UpdateClusterConfigRequest = {
        name: this.clusterName,
      };
      config2.resourcesVpcConfig = {
        endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess,
        endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess,
        publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs,
      };

      const updateResponse1 = await this.eks.updateClusterConfig(config);
      const updateResponse2 = await this.eks.updateClusterConfig(config2);
      const updateResponse = { ...updateResponse1, ...updateResponse2 };
      // some deep copy?
      return { EksUpdateId: (updateResponse.update?.id) };
    }

@watany-dev I'm not sure the suggested logic will work (even before merging the responses, which has its own issues), as when you update the cluster configuration in the first command, it transitions to an "Updating" state, and will reject any further requests until that operation is done, and the cluster is back to an "Active" state. You should have some waiting logic that ensures the cluster has applied the first update before continuing to the next operation.

@yakireliyahu1987 Thanks for adding your input on this. I would think that adding in retry logic would do the trick here.

@TheRealAmazonKendra
Copy link
Contributor

Thanks for your comment. I will re-implement this policy.

if both are true and, instead, do one update and then the other in succession.

I am embarrassed to ask this because it is an elementary question. I am having trouble getting .updateClusterConfig to return as a single value when I run it twice and return it as a single return, as in the sample below. When I try to merge updateResponse1 and updateResponse2 in the example below, the updateLogging result is overwritten by the updateAccess result. (i.e., Logging is empty).

    if (updates.updateLogging) {
      const config: aws.EKS.UpdateClusterConfigRequest = {
        name: this.clusterName,
        logging: this.newProps.logging,
      };
      if (!updates.updateAccess) {
        const updateResponse1: aws.EKS.UpdateClusterConfigResponse = await this.eks.updateClusterConfig(config);
        return { EksUpdateId: updateResponse1.update?.id };
      }

      const config2: aws.EKS.UpdateClusterConfigRequest = {
        name: this.clusterName,
      };
      config2.resourcesVpcConfig = {
        endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess,
        endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess,
        publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs,
      };

      const updateResponse1 = await this.eks.updateClusterConfig(config);
      const updateResponse2 = await this.eks.updateClusterConfig(config2);
      const updateResponse = { ...updateResponse1, ...updateResponse2 };
      // some deep copy?
      return { EksUpdateId: (updateResponse.update?.id) };
    }

Absolutely no need to be embarrassed by any questions! I'm happy to deep dive with you on this. Investing in our contributor community both helps everyone learn and helps us get better code.

Besides my generic answer of adding a retry, I'll provide some more thoughts on approaches shortly. I need to look a little closer at the codebase here. It's not one of my areas of expertise.

@TheRealAmazonKendra
Copy link
Contributor

So sorry that I didn't get back to this. I'll provide some thoughts for real on Monday.

@TheRealAmazonKendra
Copy link
Contributor

So, basically, what you want to do here is probably add a while loop around the first update being performed that waits for isUpdateComplete() to return a terminal response before starting the next update. If the first fails, you can utilize the failure handling in isActive()and let that throw an error, but if it succeeds, then performupdates.updateAccess`. Does this make sense?

@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildv2Project1C6BFA3F-wQm2hXv2jqQv
  • Commit ID: de69290
  • Result: SUCCEEDED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@watany-dev
Copy link
Contributor Author

I apologize for closing with an operational error.
I am in the process of writing a unit test of the proposed fix. I will not finish the response. I will issue another pullrequest in some form.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

(aws_eks): (EKS cluster_logging property makes cluster unmanageable)
4 participants