lib/plugins/aws/package/compile/events/schedule/index.js/AwsCompileScheduledEvents/compileScheduledEvents
class AwsCompileScheduledEvents:  compileScheduledEvents() {
    this.serverless.service.getAllFunctions().forEach((functionName) => {
      const functionObj = this.serverless.service.getFunction(functionName);
      let scheduleNumberInFunction = 0;

      if (functionObj.events) {
        functionObj.events.forEach(event => {
          if (event.schedule) {
            scheduleNumberInFunction++;
            let ScheduleExpression;
            let State;
            let Input;
            let InputPath;
            let InputTransformer;
            let Name;
            let Description;

            if (typeof event.schedule === 'object') {
              if (!this.validateScheduleSyntax(event.schedule.rate)) {
                const errorMessage = this.buildValidationErrorMessage(functionName);
                throw new this.serverless.classes
                  .Error(errorMessage);
              }
              ScheduleExpression = event.schedule.rate;
              State = 'ENABLED';
              if (event.schedule.enabled === false) {
                State = 'DISABLED';
              }
              Input = event.schedule.input;
              InputPath = event.schedule.inputPath;
              InputTransformer = event.schedule.inputTransformer;
              Name = event.schedule.name;
              Description = event.schedule.description;

              const inputOptions = [Input, InputPath, InputTransformer].filter(i => i);
              if (inputOptions.length > 1) {
                const errorMessage = [
                  'You can only set one of input, inputPath, or inputTransformer ',
                  'properties at the same time for schedule events. ',
                  'Please check the AWS docs for more info',
                ].join('');
                throw new this.serverless.classes
                  .Error(errorMessage);
              }

              if (Input && typeof Input === 'object') {
                if (_.has(Input, 'body') && typeof Input.body === 'string') {
                  try {
                    Input.body = JSON.parse(Input.body);
                  } catch (error) {
                    const errorMessage = [
                      'The body of the schedule event associated with',
                      ` ${functionName} was passed as a string`,
                      ' but it failed to parse to a JSON object.',
                      ' Please check the docs for more info.',
                    ].join('');
                    throw new this.serverless.classes
                      .Error(errorMessage);
                  }
                }
                Input = JSON.stringify(Input);
              }
              if (Input && typeof Input === 'string') {
                // escape quotes to favor JSON.parse
                Input = Input.replace(/\"/g, '\\"'); // eslint-disable-line
              }
              if (InputTransformer) {
                InputTransformer = this.formatInputTransformer(InputTransformer);
              }
            } else if (this.validateScheduleSyntax(event.schedule)) {
              ScheduleExpression = event.schedule;
              State = 'ENABLED';
            } else {
              const errorMessage = this.buildValidationErrorMessage(functionName);
              throw new this.serverless.classes
                .Error(errorMessage);
            }

            const lambdaLogicalId = this.provider.naming
              .getLambdaLogicalId(functionName);
            const scheduleLogicalId = this.provider.naming
              .getScheduleLogicalId(functionName, scheduleNumberInFunction);
            const lambdaPermissionLogicalId = this.provider.naming
              .getLambdaSchedulePermissionLogicalId(functionName, scheduleNumberInFunction);
            const scheduleId = this.provider.naming.getScheduleId(functionName);

            const scheduleTemplate = `
              {
                "Type": "AWS::Events::Rule",
                "Properties": {
                  "ScheduleExpression": "${ScheduleExpression}",
                  "State": "${State}",
                  ${Name ? `"Name": "${Name}",` : ''}
                  ${Description ? `"Description": "${Description}",` : ''}
                  "Targets": [{
                    ${Input ? `"Input": "${Input}",` : ''}
                    ${InputPath ? `"InputPath": "${InputPath}",` : ''}
                    ${InputTransformer ? `"InputTransformer": ${InputTransformer},` : ''}
                    "Arn": { "Fn::GetAtt": ["${lambdaLogicalId}", "Arn"] },
                    "Id": "${scheduleId}"
                  }]
                }
              }
            `;

            const permissionTemplate = `
              {
                "Type": "AWS::Lambda::Permission",
                "Properties": {
                  "FunctionName": { "Fn::GetAtt": ["${
              lambdaLogicalId}", "Arn"] },
                  "Action": "lambda:InvokeFunction",
                  "Principal": { "Fn::Join": ["", [ "events.", { "Ref": "AWS::URLSuffix" } ]] },
                  "SourceArn": { "Fn::GetAtt": ["${scheduleLogicalId}", "Arn"] }
                }
              }
            `;

            const newScheduleObject = {
              [scheduleLogicalId]: JSON.parse(scheduleTemplate),
            };

            const newPermissionObject = {
              [lambdaPermissionLogicalId]: JSON.parse(permissionTemplate),
            };

            _.merge(this.serverless.service.provider.compiledCloudFormationTemplate.Resources,
              newScheduleObject, newPermissionObject);
          }
        });
      }
    });
  }