aws / aws-sam-cli

CLI tool to build, test, debug, and deploy Serverless applications using AWS SAM
https://aws.amazon.com/serverless/sam/
Apache License 2.0
6.47k stars 1.16k forks source link

Bug: sam build generates template.yaml with StateMachine DefinitionUri reference file outside build folder #4786

Open DaWyz opened 1 year ago

DaWyz commented 1 year ago

Description:

When using an AWS::Serverless::StateMachine resource with DefinitionUri pointing to a local file, sam build generates the artifact in the build folder but the DefinitionUri points to a file outside the build folder.

I understand the AWS::Serverless:StateMachine doc does warn about it.

I think the result of sam build should not reference anything outside the build folder.

In our use case, we are trying to create a re-usable artifact that would work across regions and we have a StateMachine and some Lambda functions. The artifact generated by sam package only allows us to deploy in a single region. Given sam deploy executes sam package automatically, I think the re-usable artifact should be the one generated by sam build.

There was an issue created 2 years ago.

Steps to reproduce:

Given a template.yml with a StateMachine:

  MyStateMachine:
    Type: AWS::Serverless::StateMachine
    Properties:
      DefinitionUri: state_machine_definition.json

Observed result:

When I run:

sam build

Then, the generated template looks like this:

  MyStateMachine:
    Type: AWS::Serverless::StateMachine
    Properties:
      DefinitionUri: ../../state_machine_definition.json

Note The DefinitionUri of the StateMachine is pointing to the file outside the build folder.

Expected result:

In this case, similar to what building a lambda function does, I would expect sam build to copy the state_machine_definition.json into the build folder automatically and make sure the definitionUri points to that file in the build folder.

Additional environment details (Ex: Windows, Mac, Amazon Linux etc)

  1. OS: Amazon Linux
  2. sam --version: 1.68.0
  3. AWS region: us-west-2
# Paste the output of `sam --info` here

Add --debug flag to command you are running

sriram-mv commented 1 year ago

Thanks for raising this issue! Is my understanding correct that you want reproducible artifacts that encompass your application?

Seems to be also related to https://github.com/aws/aws-sam-cli/issues/4645

DaWyz commented 1 year ago

I'm not sure it's exactly related to #4645. Is that one about the lambda zips generated by sam package ? I'm targeting the output of sam build here which is quite different (nothing zipped at that stage).

mperez-bst commented 1 year ago

Hi everyone, I am facing a similar issue. When I run the command "sam build", it generates the "template.asl.json" file outside of the "build" folder. There is no problem when I do this from my terminal, as the project builds and deploys successfully. However, when I try to implement this with CI/CD, I receive an error stating that the "template.asl.json" file cannot be found.

alessandrodias-agco commented 11 months ago

Hey folks, any solution for this? I'm facing this as well! Thanks!

alessandrodias-agco commented 11 months ago

Just a FYI: we've tried to fix the path using sed after SAM build run (and before SAM deploy) by exchanging the generated template path:

sed -i "s|../../step_function_workflow.asl.json|$GITHUB_WORKSPACE/step_function_workflow.asl.json|g" .aws-sam/build/template.yaml

But then other deployment error happened:

Error: Unable to upload artifact /home/runner/work/dfs-iot-aet-acm-cleanup-service/dfs-iot-aet-acm-cleanup-service/step_function_workflow.asl.json referenced by DefinitionUri parameter of AcmCleanupServiceStateMachine resource.

S3 Bucket not specified, use --s3-bucket to specify a bucket name, or use --resolve-s3 to create a managed default bucket, or run sam deploy --guided
Error: Process completed with exit code 1.
vekee commented 6 months ago

Now, DefinitionUri seems not be supported in aws-sam-cli. Resource handler returned message: "Model validation failed (#: extraneous key [DefinitionUri] is not permitted)" (RequestToken: ce52209a-68b2-5c4a-3806-58ec37d660e5, HandlerErrorCode: InvalidRequest)

aws-resource-stepfunctions-statemachine image

My solution

buildspec.yml

version: 0.2

phases:
  install:
    runtime-versions:
      python: 3.9

  pre_build:
    commands:
      - echo "update statemachine json in samconfig.toml"
      - python template_statemachine_cf.py

  build:
    commands:
      - echo "Build started on $(date)"
      - sam build
      - echo "Deploying SAM application"
      - sam deploy

  post_build:
    commands:
      - echo Build completed on `date`

template.yml

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  SAM Template for APASYS

Parameters:
  LambdaRoleName:
    Type: "String"
    Default: "role-codepipeline-release"

Globals:
  Function:
    Runtime: python3.9
    Timeout: 3
    MemorySize: 128

Resources:
  ApasysBusinessToolsPipelineStateMachine:
    Type: AWS::StepFunctions::StateMachine
    Properties: 
      StateMachineName: 'apasys-sm-test'
      Definition: statemachine/apasys-sm-test.json
      RoleArn: 'arn:aws:iam::1234567890:role/apasys_dev_role'

template_statemachine_cf.py

import sys
import glob
import os
import json

def read_sm_def (sm_def_json_file: str) -> dict:
    try:
        with open(f"{sm_def_json_file}", "r") as file:
            return json.load(file)
    except IOError as e:
        sys.exit(1)

def list_json_files(directory):
    json_files = glob.glob(os.path.join(directory, '*.json'))
    return json_files

template_yml_file = './templates/template.yml'
for json_file in list_json_files('./src/statemachine/'):
    json_file_name_with_extension = os.path.basename(json_file)
    sm_def_dict = read_sm_def(json_file)

    with open(template_yml_file, 'r') as file:
        yaml_data = file.read()
        updated_yaml_data = yaml_data.replace('statemachine/' + json_file_name_with_extension, json.dumps(sm_def_dict))

    with open(template_yml_file, 'w') as file:
        file.write(updated_yaml_data)