Beispiel #1
0
def __execute(command, args):

    requestId = args['request_id'] if 'request_id' in args else 0

    print 'command started - {} with args {}'.format(command, args)

    metricsInterface = MetricsContext('gui')
    metricsInterface.set_command_name(command)
    metricsInterface.submit_attempt()

    try:
        argsObj = Args(**args)

        argsObj.no_prompt = True
        argsObj.is_gui = True

        context = Context(metricsInterface, view_class=GuiViewContext)
        context.bootstrap(argsObj)
        context.initialize(argsObj)

        # Deprecated in 1.9. TODO: remove.
        context.hooks.call_module_handlers(
            'cli-plugin-code/resource_commands.py',
            'add_gui_commands',
            args=[command_handlers, argsObj],
            deprecated=True)
        context.hooks.call_module_handlers(
            'cli-plugin-code/resource_commands.py',
            'add_gui_view_commands',
            args=[context.view],
            deprecated=True)

        context.hooks.call_module_handlers(
            'resource-manager-code/command.py',
            'add_gui_commands',
            kwargs={'handlers': command_handlers})

        context.hooks.call_module_handlers(
            'resource-manager-code/command.py',
            'add_gui_view_commands',
            kwargs={'view_context': context.view})

        handler = command_handlers.get(command, None)
        if handler is None:
            raise HandledError('Unknown command: ' + command)

        if handler != project.update_framework_version:
            context.config.verify_framework_version()

        handler(context, argsObj)

        context.view.success()
        metricsInterface.submit_success()

    except HandledError as e:
        metricsInterface.submit_failure()
        msg = str(e)
        print 'command error   - {} when executing command {} with args {}.'.format(
            msg, command, args)
        args['view_output_function'](requestId, 'error', msg)
    except NoCredentialsError:
        metricsInterface.submit_failure()
        msg = 'No AWS credentials were provided.'
        print 'command error   - {} when executing command {} with args {}.'.format(
            msg, command, args)
        args['view_output_function'](requestId, 'error', msg)
    except (EndpointConnectionError, IncompleteReadError, ConnectionError,
            UnknownEndpointError) as e:
        metricsInterface.submit_failure()
        msg = 'We were unable to contact your AWS endpoint.\nERROR: {0}'.format(
            e.message)
        print 'command error   - {} when executing command {} with args {}.'.format(
            msg, command, args)
        args['view_output_function'](requestId, 'error', msg)
    except:
        metricsInterface.submit_failure()
        info = sys.exc_info()
        msg = traceback.format_exception(*info)
        print 'command error   - {} when executing command {} with args {}.'.format(
            msg, command, args)
        args['view_output_function'](requestId, 'error', msg)

    print 'command finished - {} with args {}'.format(command, args)
Beispiel #2
0
def clean_custom_resource_handlers(context, args):
    if context.config.project_stack_id is None:
        raise HandledError("Project stack does not exist.")

    context.view.deleting_custom_resource_lambdas()
    lambda_client = context.aws.client('lambda',
                                       region=util.get_region_from_arn(
                                           context.config.project_stack_id))
    project_info = context.stack_info.manager.get_stack_info(
        context.config.project_stack_id)
    resource_types_used_versions = {}
    delete_count = 0

    def add_resource_versions(stack_info):
        for resource_info in stack_info.resources:
            if resource_info.type.startswith("Custom::"):
                info = custom_resource_utils.get_custom_resource_info(
                    resource_info.physical_id)
                if info.create_version:
                    resource_types_used_versions.setdefault(
                        resource_info.type, set()).add(info.create_version)
                    metadata_version = resource_info.get_cloud_canvas_metadata(
                        custom_resource_utils.METADATA_VERSION_TAG)
                    if metadata_version:
                        resource_types_used_versions[resource_info.type].add(
                            metadata_version)

    # Add the resources from the project stack, the deployment stacks, and all the resource groups
    add_resource_versions(project_info)

    for deployment_info in project_info.deployments:
        add_resource_versions(deployment_info)

        for resource_group_info in deployment_info.resource_groups:
            add_resource_versions(resource_group_info)

    # Iterate over the custom resource types
    for resource_type_name, resource_type_info in project_info.resource_definitions.iteritems(
    ):
        if resource_type_info.handler_function:
            # Obtain a list of all versions of the function
            lambda_function_name = resource_type_info.get_custom_resource_lambda_function_name(
            )
            versions = []

            for result in aws_utils.paginate(
                    lambda_client.list_versions_by_function,
                {'FunctionName': lambda_function_name}):
                versions.extend(
                    [entry['Version'] for entry in result['Versions']])

            # Walk through all versions older than the current version, and delete them if they are not in use
            assert (len(versions) >= 2)
            assert (versions[0] == "$LATEST")
            assert (int(versions[-1]) == max([int(x) for x in versions[1:]])
                    )  # Last entry should be greatest version
            in_use_versions = resource_types_used_versions.get(
                resource_type_name, set())

            for version in versions[1:-1]:
                if version not in in_use_versions:
                    context.view.deleting_lambda(lambda_function_name, version)
                    lambda_client.delete_function(
                        FunctionName=lambda_function_name, Qualifier=version)
                    delete_count += 1

    context.view.deleting_lambdas_completed(delete_count)
Beispiel #3
0
 def confirm_writable_try_again(self, path_list):
     raise HandledError('Files not writable: {}'.format(path_list))
Beispiel #4
0
def create_stack(context, args):
    """Implements the lmbr_aws initialize-project command."""

    # Supported region?
    supported_regions = __get_region_list()
    if args.region not in supported_regions:
        raise HandledError('Region {} is not supported.'.format(args.region))

    # Initialize AWS directory if needed.
    context.config.initialize_aws_directory()
    if (args.files_only):
        return

    # Already initialized?
    if context.config.local_project_settings.project_stack_exists():
        raise HandledError(
            'The project has already been initialized and is using the {} AWS Cloud Formation stack.'
            .format(context.config.project_stack_id))

    # Project settings writable?
    context.config.validate_writable(
        context.config.local_project_settings.path)

    # Is it ok to do this?
    pending_resource_status = __get_pending_resource_status(context)
    if not re.match('^[a-z](?:[a-z0-9]*[\-]?[a-z0-9]+)*$', args.stack_name,
                    re.I):
        raise HandledError(
            'Project stack name can only consist of letters, numbers, non-repeating hyphens and must start with a letter: {}'
            .format(args.stack_name))

    capabilities = context.stack.confirm_stack_operation(
        context.config.get_pending_project_stack_id(
        ),  # may be None, which is ok
        'project',
        args,
        pending_resource_status)

    # Skip creating the stack if we have already done so.
    if not context.config.get_pending_project_stack_id():

        # Use game directory name as stack name by default.
        if args.stack_name is None:
            args.stack_name = context.config.game_directory_name

        # Does a stack with the name already exist?
        if context.stack.name_exists(args.stack_name, args.region):
            message = 'An AWS Cloud Formation stack with the name {} already exists in region {}. Use the --stack-name option to provide a different name.'.format(
                args.stack_name, args.region)
            raise HandledError(message)

        # Is the stack name valid?
        util.validate_stack_name(args.stack_name)

        # Create stack using the bootstrapping template.
        context.stack.create_using_template(
            args.stack_name,
            bootstrap_template,
            args.region,
            created_callback=lambda id: context.config.
            set_pending_project_stack_id(id),
            capabilities=capabilities,
            timeoutinminutes=30)

    # Create initial project settings.
    context.config.init_project_settings()

    # Temporarily set the config's project_stack_id property to the pending stack
    # id so the project uploader can find it later.
    # context.config.project_stack_id = context.config.get_pending_project_stack_id()

    # Do the initial update...
    __update_project_stack(context, pending_resource_status, capabilities,
                           args)
Beispiel #5
0
def delete_stack(context, args):
    if context.config.project_stack_id is None:
        raise HandledError("Project stack does not exist.")

    if context.config.deployment_names:
        raise HandledError(
            'The project has {} deployment stack(s): {}. You must delete these stacks before you can delete the project stack.'
            .format(
                len(context.config.deployment_names), ', '.join(
                    deployment_name
                    for deployment_name in context.config.deployment_names)))

    if context.stack.id_exists(context.config.project_stack_id):

        retained_bucket_names = ["Configuration", "Logs"]
        retained_bucket_ids = [
            context.stack.get_physical_resource_id(
                context.config.project_stack_id,
                name,
                optional=True,
                expected_type='AWS::S3::Bucket')
            for name in retained_bucket_names
        ]

        pending_resource_status = __get_pending_resource_status(context,
                                                                deleting=True)
        context.stack.confirm_stack_operation(context.config.project_stack_id,
                                              'project stack', args,
                                              pending_resource_status)

        context.stack.delete(context.config.project_stack_id,
                             pending_resource_status=pending_resource_status)

        __delete_custom_resource_lambdas(context, args)

        for retained_bucket_name, retained_bucket_id in zip(
                retained_bucket_names, retained_bucket_ids):
            if retained_bucket_id:

                s3 = context.aws.client('s3')

                # Check to see if the bucket still exists, old versions of project-template.json
                # don't have DeletionPolicy="Retain" on this bucket.
                try:
                    s3.head_bucket(Bucket=retained_bucket_id)
                    bucket_still_exists = True
                except:
                    bucket_still_exists = False

                if bucket_still_exists:
                    stack_name = util.get_stack_name_from_arn(
                        context.config.project_stack_id)
                    util.delete_bucket_contents(context, stack_name,
                                                retained_bucket_name,
                                                retained_bucket_id)
                    context.view.deleting_bucket(retained_bucket_id)
                    s3.delete_bucket(Bucket=retained_bucket_id)

    else:

        context.view.clearing_project_stack_id(context.config.project_stack_id)

    context.config.clear_project_stack_id()
Beispiel #6
0
 def __get_gem_root_directory_path_from_gems_file_entry(self, gems_file_entry):
     relative_path = gems_file_entry.get('Path', None)
     if relative_path is None:
         raise HandledError('No Path property provided for {} in {}.'.format(gems_file_object, self.get_gems_file_path()))
     return os.path.abspath(os.path.join(self.__context.config.root_directory_path, relative_path.replace('/', os.sep)))
Beispiel #7
0
def validate_stack_name_no_reserved_words(check_name):
    if check_name in resource_type_info.LAMBDA_TAGS:
        raise HandledError('Name must not be any of %s' % sorted(list(resource_type_info.LAMBDA_TAGS)))
Beispiel #8
0
def load_template(context, template_path):
    """Reads template file content and returns it as a string."""
    try:
        return open(template_path, 'r').read()
    except IOError as e:
        raise HandledError('Could not read template from {0}.'.format(template_path))
Beispiel #9
0
def validate_stack_name_length(check_name):
    name_length = len(check_name)

    if name_length > 128:
        raise HandledError('Name is {} characters, limit 128: {}'.format(name_length, check_name))
Beispiel #10
0
def create_stack(context, args):

    # Has the project been initialized?
    if not context.config.project_initialized:
        raise HandledError('The project has not been initialized.')

    # Does a deployment with that name already exist?
    if context.config.deployment_stack_exists(args.deployment):
        raise HandledError('The project already has a {} deployment.'.format(
            args.deployment))

    # Does deployment-template.json include resource group from a gem which isn't enabled for the project?
    for resource_group_name in context.resource_groups.keys():
        __check_resource_group_gem_status(context, resource_group_name)

    # Is the deployment name valid?
    util.validate_stack_name(args.deployment)

    # If there is no project default deployment, make this the project default deployment
    if context.config.project_default_deployment is None:
        args.make_project_default = True

    # If there is no release deployment, make this the release deployment
    if context.config.release_deployment is None:
        args.make_release_deployment = True

    # Need to handle situations where the deployment and/or access stack were
    # not successfully created on previous attempts.

    pending_deployment_stack_id = context.config.get_pending_deployment_stack_id(
        args.deployment)
    pending_deployment_access_stack_id = context.config.get_pending_deployment_access_stack_id(
        args.deployment)

    pending_deployment_stack_status = context.stack.get_stack_status(
        pending_deployment_stack_id)
    pending_deployment_access_stack_status = context.stack.get_stack_status(
        pending_deployment_access_stack_id)

    # Does a stack with the name already exist? It's ok if a previous attempt
    # at creation left a stack with this name behind, we'll deal with that later.
    deployment_stack_name = args.stack_name or context.config.get_default_deployment_stack_name(
        args.deployment)
    deployment_region = util.get_region_from_arn(
        context.config.project_stack_id)
    if pending_deployment_stack_id is None or deployment_stack_name != util.get_stack_name_from_arn(
            pending_deployment_stack_id):
        if context.stack.name_exists(deployment_stack_name, deployment_region):
            raise HandledError(
                'An AWS Cloud Formation stack with the name {} already exists in region {}. Use the --stack-name option to provide a different name.'
                .format(deployment_stack_name, deployment_region))

    # Resource group (and other) file write checks
    create_and_validate_writable_list(context)

    # Is it ok to use AWS?

    pending_resource_status = __get_pending_combined_resource_status(
        context, args.deployment)

    capabilities = context.stack.confirm_stack_operation(
        None,  # stack id
        'deployment {}'.format(args.deployment),
        args,
        pending_resource_status,
        ignore_resource_types=['Custom::EmptyDeployment'])

    # We have the following scenerios to deal with:
    #
    # 1) This is the first attempt to create the deployment, or previous attempts didn't
    #    get as far as creating any stacks.
    #
    # 2) The previous attempt failed to create or update the deployment stack, which was
    # left in a ROLLBACK_COMPLETED, UPDATE_ROLLBACK_FAILED, or ROLLBACK_FAILED state. This
    # stack must be deleted and a new one created.
    #
    # 3) The previous attempt created the deployment stack but failed to create the access
    # stack, leaving it in the ROLLBACK_COMPLETED state. In this case we update the deployment
    # stack (to make sure it reflects any changes that may have been made), delete the access
    # stack and attempt to create a new one.
    #
    # 4) Both the deployment and access stacks were created successfully, but the pending
    # stack id properites in the config were not replaced with the non-pending properties
    # (this could happen if someone kills the client during the access stack creation
    # process, which then runs to a successful completion). In this case we update both
    # stacks to make sure they reflect any changes, then replace the "pending" stack id
    # properties.

    project_uploader = ProjectUploader(context)
    deployment_uploader = project_uploader.get_deployment_uploader(
        args.deployment)

    template_url = before_update(context, deployment_uploader)

    deployment_stack_parameters = __get_deployment_stack_parameters(
        context, args.deployment, uploader=deployment_uploader)

    # wait a bit for S3 to help insure that templates can be read by cloud formation
    time.sleep(constant.STACK_UPDATE_DELAY_TIME)

    try:

        if pending_deployment_stack_status not in [
                None, context.stack.STATUS_ROLLBACK_COMPLETE,
                context.stack.STATUS_DELETE_COMPLETE,
                context.stack.STATUS_UPDATE_ROLLBACK_FAILED,
                context.stack.STATUS_ROLLBACK_FAILED
        ]:

            # case 3 or 4 - deployment stack was previously created successfully, update it

            context.stack.update(pending_deployment_stack_id,
                                 template_url,
                                 deployment_stack_parameters,
                                 capabilities=capabilities)
            deployment_stack_id = pending_deployment_stack_id

        else:

            if pending_deployment_stack_status in [
                    context.stack.STATUS_ROLLBACK_COMPLETE,
                    context.stack.STATUS_ROLLBACK_FAILED,
                    context.stack.STATUS_UPDATE_ROLLBACK_FAILED
            ]:

                # case 2 - deployment stack failed to create previously, delete it

                context.stack.delete(pending_deployment_stack_id)

            # case 1 and 2 - deployment stack wasn't creatred previously or was just
            # deleted, attempt to create it

            deployment_stack_id = context.stack.create_using_url(
                deployment_stack_name,
                template_url,
                deployment_region,
                deployment_stack_parameters,
                created_callback=lambda id: context.config.
                set_pending_deployment_stack_id(args.deployment, id),
                capabilities=capabilities)

        # Now create or update the access stack...

        context.view.processing_template('{} deployment'.format(
            args.deployment))

        access_template_url = deployment_uploader.upload_content(
            constant.DEPLOYMENT_ACCESS_TEMPLATE_FILENAME,
            json.dumps(context.config.deployment_access_template_aggregator.
                       effective_template,
                       indent=4,
                       sort_keys=True),
            'processed deployment access temmplate')

        access_stack_parameters = __get_access_stack_parameters(
            context,
            args.deployment,
            deployment_stack_id=deployment_stack_id,
            uploader=deployment_uploader)

        if pending_deployment_access_stack_status not in [
                None, context.stack.STATUS_ROLLBACK_COMPLETE,
                context.stack.STATUS_DELETE_COMPLETE
        ]:

            # case 4 - access stack was previously created successfully but the pending
            # stack id properties were not replaced. Update the stack.

            context.stack.update(pending_deployment_access_stack_id,
                                 access_template_url,
                                 deployment_stack_parameters,
                                 capabilities=capabilities)

            deployment_access_stack_id = pending_deployment_access_stack_id

        else:

            if pending_deployment_access_stack_status == context.stack.STATUS_ROLLBACK_COMPLETE:

                # case 3 - access stack failed to create previously, delete it

                context.stack.delete(pending_deployment_access_stack_id)

            # case 1 or 3 - access stack wasn't created before, or was just deleted. Attempt
            # to create.

            deployment_access_stack_name = deployment_stack_name + '-Access'

            deployment_access_stack_id = context.stack.create_using_url(
                deployment_access_stack_name,
                access_template_url,
                deployment_region,
                parameters=access_stack_parameters,
                created_callback=lambda id: context.config.
                set_pending_deployment_access_stack_id(args.deployment, id),
                capabilities=capabilities)

    except:
        context.config.force_gui_refresh()
        raise

    context.config.force_gui_refresh()

    context.config.finalize_deployment_stack_ids(args.deployment)

    context.view.deployment_stack_created(args.deployment, deployment_stack_id,
                                          deployment_access_stack_id)

    # Should the new deployment become the project default deployment or the release deployment?

    if args.make_project_default:
        context.config.set_project_default_deployment(args.deployment)
        mappings.update(context, util.Args())
        context.view.default_deployment(
            context.config.user_default_deployment,
            context.config.project_default_deployment)

    if args.make_release_deployment:
        context.config.set_release_deployment(args.deployment)
        temp_args = util.Args()
        temp_args.release = True
        mappings.update(context, temp_args)
        context.view.release_deployment(context.config.release_deployment)

    after_update(context, deployment_uploader)
Beispiel #11
0
def update_stack(context, args):

    # Use default deployment if necessary

    if args.deployment is None:
        if context.config.default_deployment is None:
            raise HandledError(
                'No default deployment has been set. Provide the --deployment parameter or use the default-deployment command to set a default deployment.'
            )
        args.deployment = context.config.default_deployment

    # Does deployment-template.json include resource group from a gem which isn't enabled for the project?
    for resource_group_name in context.resource_groups.keys():
        __check_resource_group_gem_status(context, resource_group_name)

    # Resource group (and other) file write checks
    create_and_validate_writable_list(context)

    # Get necessary data, verifies project has been initialized and that the stack exists.

    deployment_stack_id = context.config.get_deployment_stack_id(
        args.deployment)
    pending_resource_status = __get_pending_deployment_resource_status(
        context, args.deployment)

    # Is it ok to do this?

    capabilities = context.stack.confirm_stack_operation(
        deployment_stack_id,
        'deployment {}'.format(args.deployment),
        args,
        pending_resource_status,
        ignore_resource_types=['Custom::EmptyDeployment'])

    # Do the upload ...

    project_uploader = ProjectUploader(context)
    deployment_uploader = project_uploader.get_deployment_uploader(
        args.deployment)

    deployment_template_url = before_update(context, deployment_uploader)

    parameters = __get_deployment_stack_parameters(
        context, args.deployment, uploader=deployment_uploader)

    # wait a bit for S3 to help insure that templates can be read by cloud formation
    time.sleep(constant.STACK_UPDATE_DELAY_TIME)

    context.stack.update(deployment_stack_id,
                         deployment_template_url,
                         parameters,
                         pending_resource_status=pending_resource_status,
                         capabilities=capabilities)

    after_update(context, deployment_uploader)

    # Update mappings...

    if args.deployment == context.config.default_deployment:
        mappings.update(context, util.Args())

    if args.deployment == context.config.release_deployment:
        temp_args = util.Args()
        temp_args.release = True
        mappings.update(context, temp_args)
Beispiel #12
0
 def name(self):
     name = self.__gem_file_object.get('Name', None)
     if name is None:
         raise HandledError('No Name property found in the gem.json file at {}'.format(self.__root_directory_path))
     return name
Beispiel #13
0
 def __gem_file_object(self):
     if self.__gem_file_object_ is None:
         if not os.path.isfile(self.__gem_file_path):
             raise HandledError('The {} directory contains no gem.json file.'.format(self.__root_directory_path))
         self.__gem_file_object_ = self.__context.config.load_json(self.__gem_file_path)
     return self.__gem_file_object_
Beispiel #14
0
 def framework_gem(self):
     framework_gem = self.get_by_name('CloudGemFramework')
     if framework_gem is None:
         raise HandledError('The CloudGemFramework gem must be enabled for the project.')
     return framework_gem
Beispiel #15
0
 def get(self, name, optional=False):
     result = self.__dict__.get(name, None)
     if result is None and not optional:
         raise HandledError(
             'The resource group {} does not exist.'.format(name))
     return result
Beispiel #16
0
def validate_stack_name_format(check_name):
    if not re.match('^[a-z][a-z0-9\-]*$', check_name, re.I):
        raise HandledError('Name can only consist of letters, numbers and hyphens and must start with a letter: {}'.format(check_name))
Beispiel #17
0
    def upload_dir(self,
                   name,
                   path,
                   extraargs=None,
                   alternate_root=None,
                   suffix=None):
        '''Creates an object in an S3 bucket using content from the specified directory.
        
        Args:

            name: Appended to the uploader's key and used as the object's
            name in the S3 bucket. A '/' will be inserted between the key
            and the specified name. Name can be None in which case the content
            of the directory will be uploaded directly under the current key.

            path: The path to the file to upload.

            alternate_root (named): if not None (the default), replaces the 
            upload/<uuid> part of the key.

        Returns:

            A string containing the URL of the uploaded file.
         
        '''

        if not os.path.isdir(path):
            raise HandledError(
                "The requested path \'{}\' is not a directory.".format(path))

        bucket = self.bucket
        key = self.key if name is None else self.key + '/' + name if self.key else name

        if alternate_root is not None:
            # expecting upload/uuid or upload/uuid/more/stuff/we/keep
            i = key.find('/')
            if i != -1:
                i = key.find('/', i + 1)
            if i == -1:
                key = alternate_root
            else:
                key = alternate_root + key[i:]
        if suffix is not None:
            key = '{}/{}'.format(key, suffix)
        self.context.view.uploading_file(bucket, key, path)
        s3 = self.context.aws.client('s3')

        for root, dirs, files in os.walk(path):
            for filename in files:
                file_path = root + '/' + filename
                relative_path = os.path.relpath(file_path, path)
                s3_path = key + '/' + relative_path
                #AWS S3 requires paths to be split by /
                s3_path = s3_path.replace("\\", "/")
                mime_type = mimetypes.guess_type(file_path)
                mime = mime_type[0]
                s3_extraargs = ({'ContentType': mime} if mime else {})
                if extraargs:
                    s3_extraargs.update(extraargs)
                try:
                    self.context.view.uploading_file(bucket, s3_path,
                                                     relative_path)
                    s3.upload_file(file_path, bucket, s3_path, s3_extraargs)
                except Exception as e:
                    raise HandledError(
                        'Cloud not upload {} to S3 bucket {} as {}.'.format(
                            path, bucket, key), e)

        return self.__make_s3_url(bucket, key)
Beispiel #18
0
    def __setup_cloud_gem_cpp_build(self, root_directory_path, gem_name, initial_content):

        aws_directory_path = os.path.join(root_directory_path, constant.GEM_AWS_DIRECTORY_NAME)

        # If there is a swagger.json file, generate service api client code.

        swagger_file_path = os.path.join(aws_directory_path, 'swagger.json')
        if os.path.exists(swagger_file_path):

            args = [
                self.__lmbr_aws_path, 
                'cloud-gem-framework', 
                'generate-service-api-code', 
                '--gem', root_directory_path, 
                '--update-waf-files']

            try:
                self.__execute(args, use_shell=True)
            except Exception as e:
                raise HandledError('Could not generate initial client code for service api. {}'.format(e.message))
        
        # Use the initial-content option to determine what additional AWS SDK libs are needed.
        # We don't expect game clients to directly access most AWS services (TODO: game 
        # servers). 
        #
        # The resource-manager-plugin initial content doesn't require any AWS API support, so
        # we leave the wscript alone in that case. Initial content starting with 'api' only
        # needs AWS SDK Core.
        #
        # Unfortuantly we can't easly modify the origional wscript file. Since it was just
        # created it should still have only the default, we just overwrite it. 
        #
        # We also write an aws_unsupported.waf_files, which is specified by the wscript for
        # platforms that do not support AWS. This includes onl the minimal files needed to
        # get the gem to build.

        if initial_content != 'resource-manager-plugin':

            use_lib_list = [ 'AWS_CPP_SDK_CORE' ]
            if initial_content.startswith('lambda'):
                use_lib_list.append('AWS_CPP_SDK_LAMBDA')
            elif initial_content.startswith('bucket'):
                use_lib_list.append('AWS_CPP_SDK_S3')

            wscript_file_path = os.path.join(root_directory_path, 'Code', 'wscript')
            self.__context.view.saving_file(wscript_file_path)
            with open(wscript_file_path, 'w') as file:
                wscript_content = CLOUD_GEM_WSCRIPT_FILE_CONTENT
                wscript_content = wscript_content.replace('$-GEM-NAME-LOWER-CASE-$', gem_name.lower())
                wscript_content = wscript_content.replace('$-USE-LIB-LIST-$', str(use_lib_list))
                file.write(wscript_content)

            unsupported_waf_files_file_path = os.path.join(root_directory_path, 'Code', 'aws_unsupported.waf_files')
            self.__context.view.saving_file(unsupported_waf_files_file_path)
            with open(unsupported_waf_files_file_path, 'w') as file:
                aws_unsupported_file_content = AWS_UNSUPPORTED_WAF_FILES_FILE_CONTENT.replace('$-GEM-NAME-$', gem_name)
                file.write(aws_unsupported_file_content)

            gem_file_path = os.path.join(root_directory_path, 'gem.json')
            gem_file_content = util.load_json(gem_file_path, optional = False)
            gem_uuid = gem_file_content.get('Uuid', None)
            if gem_uuid is None:
                raise HandledError('Missing required Uuid property in {}.'.format(gem_file_path))

            component_stub_cpp_file_path = os.path.join(root_directory_path, 'Code', 'Source', 'ComponentStub.cpp')
            self.__context.view.saving_file(component_stub_cpp_file_path)
            with open(component_stub_cpp_file_path, 'w') as file:
                component_stub_cpp_file_content = COMPONENT_STUB_CPP_FILE_CONTENT.replace('$-GEM-NAME-$', gem_name)
                component_stub_cpp_file_content = COMPONENT_STUB_CPP_FILE_CONTENT.replace('$-GEM-UUID-$', gem_uuid)
                file.write(component_stub_cpp_file_content)