aws-cloudformation / cloudformation-coverage-roadmap

The AWS CloudFormation Public Coverage Roadmap
https://aws.amazon.com/cloudformation/
Creative Commons Attribution Share Alike 4.0 International
1.11k stars 56 forks source link

AWS::Scheduler::ScheduleGroup - Cannot create: Unable to retrieve Arn attribute for AWS::Scheduler::Schedule #1726

Open FarrOut opened 1 year ago

FarrOut commented 1 year ago

Name of the resource

AWS::Scheduler::ScheduleGroup

Resource Name

AWS::Scheduler::ScheduleGroup

Issue Description

Cannot create a stack which contains a AWS::Scheduler::ScheduleGroup and a AWS::Scheduler::Schedule.

Expected Behavior

Stack creates successfully.

Observed Behavior

Stack creation fails with the following error message on stack-level..

Unable to retrieve Arn attribute for AWS::Scheduler::Schedule, with error message Resource of type 'AWS::Scheduler::Schedule' with identifier 'SchedulerStack-MyCfnSchedule-XXXXXXX' was not found.. Rollback requested by user.

Test Cases

CDK

from aws_cdk import (
    # Duration,
    Stack, CfnOutput,
    aws_scheduler as scheduler, aws_lambda as lambda_, RemovalPolicy,
)
from aws_cdk.aws_iam import ManagedPolicy, Role, ServicePrincipal
from aws_cdk.aws_lambda import Runtime, Code
from aws_cdk.aws_scheduler import CfnSchedule
from constructs import Construct

class SchedulerStack(Stack):

    def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        managed_policy_arn = \
            ManagedPolicy.from_aws_managed_policy_name('AmazonEventBridgeSchedulerFullAccess')

        schedule_role = Role(self, "Role",
                             assumed_by=ServicePrincipal("scheduler.amazonaws.com"),
                             # custom description if desired
                             description="This is a custom role...",
                             managed_policies=[managed_policy_arn],
                             )
        schedule_role.apply_removal_policy(RemovalPolicy.DESTROY)

        fn = lambda_.Function(self, "lambda_function",
                              runtime=Runtime.NODEJS_18_X,
                              handler="index.handler",
                              code=Code.from_inline('exports.handler = handler.toString() //'))

        schedule_group = scheduler.CfnScheduleGroup(self, "MyScheduleGroup",
                                                    name="GroupOfSchedules", )

        CfnOutput(self, 'ScheduleGroupName',
                  description='The Name attribute of the schedule group.',
                  value=str(schedule_group.name)
                  )
        CfnOutput(self, 'ScheduleGroupArn',
                  description='The ARN of the schedule group.',
                  value=str(schedule_group.attr_arn)
                  )

        self.schedule = scheduler.CfnSchedule(self, "MyCfnSchedule",
                                              # name='theschedule',
                                              group_name=schedule_group.name,
                                              flexible_time_window=scheduler.CfnSchedule.FlexibleTimeWindowProperty(
                                                  mode="OFF",
                                              ),
                                              state='ENABLED',
                                              schedule_expression="rate(5 minutes)",
                                              schedule_expression_timezone="Europe/Berlin",
                                              target=CfnSchedule.TargetProperty(
                                                  arn=fn.function_arn,
                                                  role_arn=schedule_role.role_arn,
                                              ),
                                              )

        CfnOutput(self, 'ScheduleName',
                  description='The Name attribute of the schedule.',
                  value=str(self.schedule.ref)
                  )
        CfnOutput(self, 'ScheduleArn',
                  description='The ARN of the schedule.',
                  value=str(self.schedule.attr_arn)
                  )

CFN

Resources:
  Role1ABCC5F0:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Action: sts:AssumeRole
            Effect: Allow
            Principal:
              Service: scheduler.amazonaws.com
        Version: 2012-10-17
      Description: This is a custom role...
      ManagedPolicyArns:
        - Fn::Join:
            - ''
            - - 'arn:'
              - Ref: AWS::Partition
              - :iam::aws:policy/AmazonEventBridgeSchedulerFullAccess
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
  lambdafunctionServiceRole85538ADB:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Action: sts:AssumeRole
            Effect: Allow
            Principal:
              Service: lambda.amazonaws.com
        Version: 2012-10-17
      ManagedPolicyArns:
        - Fn::Join:
            - ''
            - - 'arn:'
              - Ref: AWS::Partition
              - :iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
  lambdafunction45C982D3:
    Type: AWS::Lambda::Function
    Properties:
      Code:
        ZipFile: exports.handler = handler.toString() //
      Role:
        Fn::GetAtt:
          - lambdafunctionServiceRole85538ADB
          - Arn
      Handler: index.handler
      Runtime: nodejs18.x
    DependsOn:
      - lambdafunctionServiceRole85538ADB
  MyScheduleGroup:
    Type: AWS::Scheduler::ScheduleGroup
    Properties:
      Name: GroupOfSchedules
  MyCfnSchedule:
    Type: AWS::Scheduler::Schedule
    Properties:
      FlexibleTimeWindow:
        Mode: OFF
      ScheduleExpression: rate(5 minutes)
      Target:
        Arn:
          Fn::GetAtt:
            - lambdafunction45C982D3
            - Arn
        RoleArn:
          Fn::GetAtt:
            - Role1ABCC5F0
            - Arn
      GroupName: GroupOfSchedules
      ScheduleExpressionTimezone: Europe/Berlin
      State: ENABLED
Outputs:
  ScheduleGroupName:
    Description: The Name attribute of the schedule group.
    Value: GroupOfSchedules
  ScheduleName:
    Description: The Name attribute of the schedule.
    Value:
      Ref: MyCfnSchedule
  ScheduleArn:
    Description: The ARN of the schedule.
    Value:
      Fn::GetAtt:
        - MyCfnSchedule
        - Arn

Other Details

No response

FarrOut commented 1 year ago

Interestingly when attempting to get info on an already created Schedule using get-schedule, it fails to find the it (ResourceNotFound). If a Schedule is associated to a ScheduleGroup, the --group-name flag must be provided.

It would be nice to have more explicit feedback to know why the existing resource cannot be found.

thinhlh commented 2 months ago

I am facing this issue with the following CF setup. Do we have any resolve for this?

{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Description": "CloudFormation template to create an Event Bridge",
    "Parameters": {
        "EventBridgeRoleArn": {
            "Type": "String",
            "Description": "IAM Role for event bridge"
        },
        "StepFunctionArn": {
            "Type": "String",
            "Description": "Step Function Arn"
        }
    },
    "Resources": {
        "DailyJobScheduleGroup": {
            "Type": "AWS::Scheduler::ScheduleGroup",
            "Properties": {
                "Name": "daily-job-schedule-group-cf"
            }
        },
        "DailyBatchJobSchedule": {
            "Type": "AWS::Scheduler::Schedule",
            "DependsOn": [
                "DailyJobScheduleGroup"
            ],
            "Properties": {
                "Name": "batch-jobs-scheduler-test-cf",
                "Description": "Execute batch jobs daily",
                "State": "DISABLED",
                "ScheduleExpression": "cron(0 0 * * ? *)",
                "FlexibleTimeWindow": {
                    "Mode": "OFF"
                },
                "Target": {
                    "Arn": {
                        "Ref": "StepFunctionArn"
                    },
                    "RoleArn": {
                        "Ref": "EventBridgeRoleArn"
                    },
                    "RetryPolicy": {
                        "MaximumEventAgeInSeconds": 86400,
                        "MaximumRetryAttempts": 0
                    }
                }
            }
        }
    },
    "Outputs": {
        "DailyEventBridgeArn": {
            "Description": "ARN of the created daily event bridge",
            "Value": {
                "Fn::GetAtt": [
                    "DailyBatchJobSchedule",
                    "Arn"
                ]
            }
        }
    }
}
alexru-sportsbet commented 2 months ago

I am also facing this issue. Cannot get Scheduler ARN since I add a GroupName property to my scheduler

alanwill commented 1 month ago

Found this issue while troubleshooting the same problem. It's been over a year since it's been raised, bummer no response from anyone at AWS as it's clearly a real problem.