code: func callServiceDecoratorHook(ctx *workflowContext) error {
  	if ctx.userdata.workflowHooks == nil {
  		return nil
  	}
  	serviceHooks := ctx.userdata.workflowHooks.ServiceDecorators
  	if ctx.userdata.workflowHooks.ServiceDecorator != nil {
  		ctx.logger.Warn("DEPRECATED: Single ServiceDecorator hook superseded by ServiceDecorators slice")
  		serviceHooks = append(serviceHooks,
  			ServiceDecoratorHookFunc(ctx.userdata.workflowHooks.ServiceDecorator))
  	}
  	// If there's an API gateway definition, include the resources that provision it.
  	// Since this export will likely
  	// generate outputs that the s3 site needs, we'll use a temporary outputs accumulator,
  	// pass that to the S3Site
  	// if it's defined, and then merge it with the normal output map.-
  	for _, eachServiceHook := range serviceHooks {
  		hookName := runtime.FuncForPC(reflect.ValueOf(eachServiceHook).Pointer()).Name()
  		ctx.logger.WithFields(logrus.Fields{
  			"ServiceDecoratorHook": hookName,
  			"WorkflowHookContext":  ctx.context.workflowHooksContext,
  		}).Info("Calling WorkflowHook")
  
  		serviceTemplate := gocf.NewTemplate()
  		decoratorError := eachServiceHook.DecorateService(ctx.context.workflowHooksContext,
  			ctx.userdata.serviceName,
  			serviceTemplate,
  			ctx.userdata.s3Bucket,
  			codeZipKey(ctx.context.s3CodeZipURL),
  			ctx.userdata.buildID,
  			ctx.context.awsSession,
  			ctx.userdata.noop,
  			ctx.logger)
  		if nil != decoratorError {
  			return decoratorError
  		}
  		safeMergeErrs := gocc.SafeMerge(serviceTemplate, ctx.context.cfTemplate)
  		if len(safeMergeErrs) != 0 {
  			return errors.Errorf("Failed to merge templates: %#v", safeMergeErrs)
  		}
  	}
  	return nil
  }
docs: // Encapsulate calling the service decorator hooks