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

(aws-apigateway): RestApi imported with method fromRestApiAttributes not updating current deployment in stage #13526

Closed
benticlaskaris opened this issue Mar 10, 2021 · 21 comments
Assignees
Labels
@aws-cdk/aws-apigateway Related to Amazon API Gateway bug This issue is a bug. needs-reproduction This issue needs reproduction. p2

Comments

@benticlaskaris
Copy link

benticlaskaris commented Mar 10, 2021

I've imported from a serverless project this restApi.

const restApiId = cdk.Fn.importValue(envRelated(`ApiGateway-restApiId`));
const rootResourceId = cdk.Fn.importValue(envRelated(`ApiGateway-rootResourceId`));
this.apiGw = apigateway.RestApi.fromRestApiAttributes(this, envRelated(`apigw`), {
	restApiId: restApiId,
	rootResourceId: rootResourceId,
});

When deploying with cdk deploy, all resources are updated but not the stage.
No deployment is created.
I've tried also to force a deployment with this snippet.

new Deployment(this,envRelated('deployment-stage') , {
      api: apiGw
    });

Salting the deployment id makes no difference.
After the deployment is done, the api gateway is still pointing to the previous deployment instead of the new deployment done.

chrome_sGUK4TBoqT

Specifying the stage with the forced deployment fails because stage already exists.

Environment

  • CDK CLI Version: 1.9.2
  • Module Version: 1.9.2
  • Node.js Version: 12.14.1
  • OS: Ubuntu Linux 20.04
  • **Language: ts
@github-actions github-actions bot added the @aws-cdk/aws-apigateway Related to Amazon API Gateway label Mar 10, 2021
@benticlaskaris benticlaskaris changed the title (aws-apigateway): RestApi imported with fromRestApiAttributes not updating current deployment in stage (aws-apigateway): RestApi imported with method fromRestApiAttributes not updating current deployment in stage Mar 10, 2021
@baumannalexj
Copy link

baumannalexj commented Mar 11, 2021

@evilsephiroth try this

you need to bust the deployment sha with addToLogicalId

const apiDeployment = new cdkApiGateway.Deployment(this, `api-deployment`, {
            api: <importedApi>,
            description: `maybe put datetime or artifact version here`,
            retainDeployments: true,
        });
        apiDeployment.addToLogicalId( new Date().toISOString() ); //need to change deployment hash to force new deployment

and for a specific stage

        apiDeployment.resource.stageName = <your stage name>;          // https://stackoverflow.com/a/64369331/6791342 // if the 'stageName' already exists (from the core apigateway deployment) then the existing stage will be used !


@benticlaskaris
Copy link
Author

benticlaskaris commented Mar 11, 2021

@evilsephiroth try this

you need to bust the deployment sha with addToLogicalId

const apiDeployment = new cdkApiGateway.Deployment(this, `api-deployment`, {
            api: <importedApi>,
            description: `maybe put datetime or artifact version here`,
            retainDeployments: true,
        });
        apiDeployment.addToLogicalId( new Date().toISOString() ); //need force change deployment hash to force new deployment

and for a specific stage

        apiDeployment.resource.stageName = <your stage name>;          // https://stackoverflow.com/a/64369331/6791342 // if the 'stageName' already exists (from the core apigateway deployment) then the existing stage will be used !

Added the logicalId but no change. Still the deployment occurs but it's not selecting the latest deployment in the stage.
And apideployment.resource.stageName won't compile in 1.92 version.
As I said previously, the deployment is done without problems but it's not correctly set as current stage in deploymentHistory as in my screenshot.

@NGL321 NGL321 added bug This issue is a bug. needs-reproduction This issue needs reproduction. p2 labels Jul 24, 2021
@NGL321
Copy link
Contributor

NGL321 commented Jul 24, 2021

Hey @evilsephiroth,

I am unsure as to why this was not correctly marked as a bug report, but I have now corrected it. Someone from the team will attempt to reproduce your issue as soon as able. Please let us know if you have any updates, and we will update this issue when there is an opportunity to investigate further.

@nemanjko
Copy link

nemanjko commented Aug 8, 2021

@evilsephiroth I have the same issue.

Unable to run new deployment to update a stage in API Gateway. Tried previous suggestion by @ baumannalexj but still the same.

The workaround I use is to run Lambda custom resource and trigger the deployment explicitly:

response = boto3.client.create_deployment(
    restApiId='hvgcqh4dgk',
    stageName='device4'
)

@gawdzer
Copy link

gawdzer commented Aug 22, 2021

Hey @evilsephiroth,

I am unsure as to why this was not correctly marked as a bug report, but I have now corrected it. Someone from the team will attempt to reproduce your issue as soon as able. Please let us know if you have any updates, and we will update this issue when there is an opportunity to investigate further.

We're having the same issue as well :[

@nija-at
Copy link
Contributor

nija-at commented Sep 3, 2021

Sounds like the same as #12417.

You will need to manually salt your deployment every time any resource changes. This is a limitation of the fromRestApiAttributes() method.

Please upvote the feature request for prioritization.

@nija-at nija-at added the response-requested Waiting on additional info and feedback. Will move to "closing-soon" in 7 days. label Sep 3, 2021
@nija-at
Copy link
Contributor

nija-at commented Sep 3, 2021

Here's how to salt your own deployment -

const logicalId = // salted id
const cfnDeployment = deployment.node.defaultChild as CfnDeployment;
cfnDeployment.overrideLogicalId(logicalId);

The value of the logicalId here should be such that it changes every time a Resource or Method is modified, and this stack must be deployed last.

@gawdzer
Copy link

gawdzer commented Sep 13, 2021

Here's how to salt your own deployment -

const logicalId = // salted id
const cfnDeployment = deployment.node.defaultChild as CfnDeployment;
cfnDeployment.overrideLogicalId(logicalId);

The value of the logicalId here should be such that it changes every time a Resource or Method is modified, and this stack must be deployed last.

Changing the value of the logicalId does not affect the result: One can create a new deployment, but it's impossible to set is as the 'active' deployment for an already-existing stage.

@github-actions github-actions bot removed the response-requested Waiting on additional info and feedback. Will move to "closing-soon" in 7 days. label Sep 21, 2021
@hassanazharkhan
Copy link
Contributor

@gawdzer @nemanjko Since you both were facing the same issue, Did you have any luck with the fix of this one?

I'm facing the same issue as well now, I even tried every possible solution for this but no luck so far, any help would be greatly appreciated

@otaviomacedo otaviomacedo self-assigned this Jan 12, 2022
@otaviomacedo
Copy link
Contributor

The deployment is not set as the current one because when you import a RestApi, the generated template doesn't have a AWS::ApiGateway::Stage resource. It only has a AWS::ApiGateway::Method and a AWS::ApiGateway::Deployment. Therefore you can change the deployment as much as you want, but the stages of the imported API will keep pointing to whatever Deployments they were pointing to before.

So the only workaround I can see is to define your own stages:

const api = RestApi.fromRestApiAttributes(this, 'api', {...});

const deployment = new Deployment(this, 'deployment', { api });

const logicalId = // salted id
const cfnDeployment = deployment.node.defaultChild as CfnDeployment;
cfnDeployment.overrideLogicalId(logicalId);

new Stage(this, 'stage', {
  stageName: 'stage-created-by-cdk', // this stage will have the new deployment. Others will stay the same
  deployment,
});

@hassanazharkhan
Copy link
Contributor

@otaviomacedo So just to sum up there is no way to set the Deployments to the current stage if the RestApi is imported using CDK?

FYI, I'm able to set the current deployment using the console

@otaviomacedo
Copy link
Contributor

@otaviomacedo So just to sum up there is no way to set the Deployments to the current stage if the RestApi is imported using CDK?

That's right.

@github-actions
Copy link

⚠️COMMENT VISIBILITY WARNING⚠️

Comments on closed issues are hard for our team to see.
If you need more assistance, please either tag a team member or open a new issue that references this one.
If you wish to keep having a conversation with other community members under this issue feel free to do so.

@montoyan877
Copy link

Any news on this topic?

@Simonl9l
Copy link

Simonl9l commented Nov 9, 2022

@otaviomacedo, @hassanazharkhan, @nija-at, @NGL321 et al - I have a similar related unresolved issue - per this it seem a way to deploy to an existing stage is via deployment.resource.stageName = 'YourStageName';

However in dotnet/C# this property is not accessible.

I also note that Stage.FromStageAttributes per the CDK dotnet documentation does not seem to exist, at least in version 2.43.1, not that this would help but a divergence of assembly vs documentation.

I'm essentially importing the RestApi into a number of different stacks via RestApi.FromRestApiAttributes, adding Resources as applicable for that stack and then need to deploy it, in each case; but see no way to do it specifically in DotNet/C#

I need to redeploy the same stage each time but get the error prod already exists in stack.

@minhhuynh-smg
Copy link

Why this topic was closed? This issue seems to be still a valid request for the feature of imported RestApi.

@Simonl9l
Copy link

Simonl9l commented Feb 5, 2023

@minhhuynh-smg I’d tagged team members per the bot instructions to no avail. Someone probably need to “open new issue referencing this one”

@muzeke
Copy link

muzeke commented Mar 28, 2023

Wondering if anyone has ever got a working solution for this problem as We are currently experiencing the same issue. One thing i noticed though, looking at the deployment history it seems that it always points to the latest deployment but my changes on the api resources and methods are not working when i test the endpoints. (I will either have to manually do deploy in aws console UI or do cdk deploy twice to make it work)

const deployment = new apigateway.Deployment(
    scope,
    'Deployment',
    {
      api: restApi,
    }
  );

  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
  // @ts-ignore
  deployment.resource.stageName = 'main';

  const logicalId = Date.now().toString(); // salted id
  deployment.addToLogicalId(logicalId);

UPDATE :
After trying around a couple of things, I stumbled upon trying this

deployment.node.addDependency(resource);

somehow this solves my issue, my changes is now being deployed and reflecting as soon as the cdk deploy is completed.

Here is the complete code:

const resource = apigateway.Resource.fromResourceAttributes( .....

const deployment = new apigateway.Deployment(
    scope,
    'Deployment',
    {
      api: restApi,
    }
  );
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
  // @ts-ignore
  deployment.resource.stageName = 'main';

  const logicalId = Date.now().toString(); // salted id
  deployment.addToLogicalId(logicalId);

  deployment.node.addDependency(resource);

@jmihalich
Copy link

jmihalich commented Jul 25, 2023

Seriously guys, I'm tired of this. CDK Development is 95% google search, and 5% actual coding. The documentation is horrendous, you really need to make it a priority to update it. The above almost worked for me. The issue, if you look at the template, is that the deployment is created in parallel with everything else if there is no dependency on anything, and winds up running first before the actual new resource or whatever is applied to an existing gateway. I couldn't depend on the "FromResourceAttribute" object cuz it didn't add a dependency to the template for some reason. I had to have the Deployment depend on the new resource I added. For those who find this, here is example .Net code that worked for me. You can convert this to the language of your choice: (Btw, this is CDK V2 code from version 2.88.0)

` var stack = new Stack(scope, id, stackProps);

    var function = new Function(stack, "TestFunction", new FunctionProps()
    {
	    //NOTE: Substitute withyour own new lambda code
        FunctionName = "MyTestFunction",
        Runtime = Runtime.PYTHON_3_10,
        Code = Code.FromAsset("lambda"),
        Handler = "lambda_function.lambda_handler"
    });

    var restApi = RestApi.FromRestApiAttributes(stack, "ExistingRestApi2", new RestApiAttributes()
    {
	    //You have to export the api-gateway-api-id and api-gateway-root-resource-id values as CfnOutputs from your main stack that initially deployed the gateway.
        RestApiId = Fn.ImportValue("api-gateway-api-id"),
        RootResourceId = Fn.ImportValue("api-gateway-root-resource-id")
    });

    var stage = Amazon.CDK.AWS.APIGateway.Stage.FromStageAttributes(stack, "PublicAPIStage", new StageAttributes()
    {
        RestApi = restApi,
		
		//Replace with your existing stage name
        StageName = "public-api"
    });

    var newResource = restApi.Root.AddResource("graph");
    newResource.AddProxy(new ProxyResourceOptions()
    {
        DefaultIntegration = new LambdaIntegration(function),
        AnyMethod = true,
        DefaultMethodOptions = new MethodOptions()
        {
            AuthorizationType = AuthorizationType.NONE
        }
    });
    newResource.Node.AddDependency(function);

    var deployment = new Deployment(stack, "ApiTestDeployment", new DeploymentProps()
    {
        Api = restApi,
        RetainDeployments = false,
    });
	
	//this salts the deployment
    deployment.AddToLogicalId(DateTime.UtcNow.ToString());
	
    //make the deployment dependent on the resource so it runs last
    deployment.Node.AddDependency(newResource);

    //StageName is unavailable in the L2 deployment class, so you need to get the L1 resource.
    var cfnDeployment = (CfnDeployment)deployment.Node.DefaultChild!;
	
	//set the name of the stage on the L1 deployment object.
    cfnDeployment.StageName = "public-api";`

@Simonl9l
Copy link

Simonl9l commented Jul 27, 2023

@jmihalich agreed all around...TF CDK (or pulumi) looks better every day - since feet is all we have!

Will try your approach out!

@defaultusername8
Copy link

defaultusername8 commented Oct 5, 2023

For anyone who might have the same problem:

after some experimenting, just modifying the latestDeployment logical id worked for me without creating my own deployment. I suspect that might not always work (in my case, I was doing a change to only lambda integration properties and it was not ending up in a apigw deployment at all - not only was the deployment not active, but it was not even created), but it's worth a shot before messing with creating your own deployment and having the deploy: true option bug out.

code:

{
// messing around with api properties that I assume do not end up in the hash
}
const apiGateway = new SpecRestApi(
    scope,
    `MyRestApiGateway`,
    {
      apiDefinition: ApiDefinition.fromInline(apiDefinitionJSON),
      restApiName: `MyRestApiGatewayName`,
      deploy: true
      ...
     }
  apiGateway.latestDeployment?.addToLogicalId(Date.now());


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
@aws-cdk/aws-apigateway Related to Amazon API Gateway bug This issue is a bug. needs-reproduction This issue needs reproduction. p2
Projects
None yet
Development

No branches or pull requests