1

I am creating a Step Function State machine to everytime an instance starts it copy a file from S3 to an specific folder inside this instance. The origin folder inside S3 bucket has a folder named with this instance ID. The instance ID I am passing as input for the System manager block, but I need to use it to create the command string that will be performed inside the EC2.

For example:

My input is: $.detail.instance-id (lets assume the following ID i-11223344556677889)

The Systems Manager API parameters are:

  "CloudWatchOutputConfig": {
    "CloudWatchLogGroupName": "myloggroup",
    "CloudWatchOutputEnabled": true
  },
  "DocumentName": "AWS-RunShellScript",
  "DocumentVersion": "$DEFAULT",
  "InstanceIds.$": "States.Array($)",
  "MaxConcurrency": "50",
  "MaxErrors": "10",
  "Parameters": {
    "commands": [
      {
        "runuser -l ec2-user -c \"aws s3 cp s3://my-bucket/**MY_INSTANCEID**/myfile.xyz /home/ec2-user/myfolder/myfile.xyz\""
      }
  },
  "TimeoutSeconds": 6000
}```

Summing up, I want to turn the line with the command replacing the MY_INSTANCEID by my input $.detail.instance-id, and perform the following command:

"runuser -l ec2-user -c "aws s3 cp s3://my-bucket/i-11223344556677889/myfile.xyz /home/ec2-user/myfolder/myfile.xyz""

Is there a way? I already tried to use the Fn::join withou success.

Thank you in advance, kind regards,

Winner

5
  • 1
    Check out this question. Does States.Format work for your case? stackoverflow.com/questions/70766536/…. Commented Jan 22, 2022 at 1:56
  • why not use ec2 user-data? That already runs at boot in the context of the instance docs.aws.amazon.com/AWSEC2/latest/UserGuide/user-data.html you can get the ID from the instance metadata service: docs.aws.amazon.com/AWSEC2/latest/UserGuide/…. I'm not sure why you'd key the object path off instance ID, as you won't know them beforehand. If you modify some base file for each instance, you may as well pull the template and modify it on the instance Commented Jan 22, 2022 at 2:08
  • @RegisterSole, I've tryed this as solution but I got stuck. I don't know if I am having a mistake using all those quotes "Parameters": { "commands.$": "States.Format('runuser -l ec2-user -c \"aws s3 cp s3://my-bucket/{}/myfile.xyz /home/ec2-user/myfolder/myfile.xyz\"', $.detail.instance-id)" }, I getting the following error: The value for the field 'commands.$' must be a valid JSONPat Commented Jan 24, 2022 at 23:19
  • @DanielFarrell, if theres no possibility to do using Step Functions maybe this can be the solution. Commented Jan 24, 2022 at 23:20
  • @WinnerMartins Backslash is a special character. See the reserved character section here docs.aws.amazon.com/step-functions/latest/dg/…. I'm not sure the correct way though, I think either escape it like instead of \", use \\", or maybe if it doesn’t work remove it altogether ". Commented Jan 25, 2022 at 1:53

1 Answer 1

0

It was necessary to use State.Format inside the State.Array so the it worked, and State.Format inside the State.Array cannot have quotes:

  "CloudWatchOutputConfig": {
    "CloudWatchLogGroupName": "myloggroup",
    "CloudWatchOutputEnabled": true
  },
  "DocumentName": "AWS-RunShellScript",
  "DocumentVersion": "$DEFAULT",
  "InstanceIds.$": "States.Array($)",
  "MaxConcurrency": "50",
  "MaxErrors": "10",
  "Parameters": {
    "commands.$": "States.Array(States.Format('runuser -l ec2-user -c \"aws s3 cp s3://my-bucket/**MY_INSTANCEID**/myfile.xyz /home/ec2-user/myfolder/myfile.xyz\"', $))"
  },
  "TimeoutSeconds": 6000
}```

Was also necessary to use .$ after command.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.