Ejemplo n.º 1
0
    def setUp(self):
        waiter = mock.Mock()
        waiter.wait.return_value = {}
        mock_cd = mock.Mock()
        mock_cd.get_waiter.return_value = waiter

        self.deployer = CodeDeployer(mock_cd, self.TEST_APPSPEC)
Ejemplo n.º 2
0
 def setUp(self):
     super(TestDeployCommand, self).setUp()
     # setup required values
     files = FileCreator()
     self.task_def_file = files.create_file(
         'taskDef.json', json.dumps(self.TASK_DEFINITION_JSON), mode='w')
     self.appspec_file = files.create_file(
         'appspec.yaml', self.YAML_APPSPEC, mode='w')
     self.appspec_file_json = files.create_file(
         'appspec.json', self.JSON_APPSPEC, mode='w')
     self.service_name = 'serviceTest'
     self.service_arn = 'arn:aws:ecs:::service/serviceTest'
     # setup default optional values
     self.cluster_name = 'default'
     self.cluster_arn = 'arn:aws:ecs:::cluster/default'
     self.application_name = get_app_name(
         self.service_name, self.cluster_name, None)
     self.deployment_group_name = get_deploy_group_name(
         self.service_name, self.cluster_name, None)
     # setup test response resources
     self.missing_properties_appspec = files.create_file(
         'appspec_bad.yaml', self.BAD_APPSPEC, mode='w')
     self.task_definition_arn = \
         'arn:aws:ecs::1234567890:task-definition\\test:2'
     self.deployment_id = 'd-1234567XX'
     self.mock_deployer = CodeDeployer(None, self.APPSPEC_DICT)
     self.mock_deployer.update_task_def_arn(self.task_definition_arn)
     self.expected_stdout = ("Successfully registered new ECS task "
                             "definition " + self.task_definition_arn + "\n"
                             "Successfully created deployment " +
                             self.deployment_id + "\n"
                             "Waiting for " + self.deployment_id +
                             " to succeed...\nSuccessfully deployed "
                             + self.task_definition_arn + " to service '"
                             + self.service_name + "'\n")
Ejemplo n.º 3
0
    def test_update_task_def_arn_error_required_key(self):
        invalid_appspec = {
            "version": 0.0,
            "resources": [{
                "TestFunc": {
                    "type": "AWS::Lambda::Function",
                    "properties": {
                        "name": "some-function"
                    }
                }
            }]
        }
        bad_deployer = CodeDeployer(None, invalid_appspec)

        with self.assertRaises(MissingPropertyError):
            bad_deployer.update_task_def_arn('arn:aws:ecs:task-definiton/test')
Ejemplo n.º 4
0
    def setUp(self):
        waiter = mock.Mock()
        waiter.wait.return_value = {}
        mock_cd = mock.Mock()
        mock_cd.get_waiter.return_value = waiter

        self.deployer = CodeDeployer(mock_cd, self.TEST_APPSPEC)
Ejemplo n.º 5
0
    def test_update_task_def_arn_error_required_key(self):
        invalid_appspec = {
            "version":
            0.0,
            "resources": [{
                "TestFunc": {
                    "type": "AWS::Lambda::Function",
                    "properties": {
                        "name": "some-function"
                    }
                }
            }]
        }
        bad_deployer = CodeDeployer(None, invalid_appspec)

        with self.assertRaises(MissingPropertyError):
            bad_deployer.update_task_def_arn('arn:aws:ecs:task-definiton/test')
Ejemplo n.º 6
0
 def setUp(self):
     super(TestDeployCommand, self).setUp()
     # setup required values
     files = FileCreator()
     self.task_def_file = files.create_file('taskDef.json',
                                            json.dumps(
                                                self.TASK_DEFINITION_JSON),
                                            mode='w')
     self.appspec_file = files.create_file('appspec.yaml',
                                           self.YAML_APPSPEC,
                                           mode='w')
     self.appspec_file_json = files.create_file('appspec.json',
                                                self.JSON_APPSPEC,
                                                mode='w')
     self.service_name = 'serviceTest'
     self.service_arn = 'arn:aws:ecs:::service/serviceTest'
     # setup default optional values
     self.cluster_name = 'default'
     self.cluster_arn = 'arn:aws:ecs:::cluster/default'
     self.application_name = get_app_name(self.service_name,
                                          self.cluster_name, None)
     self.deployment_group_name = get_deploy_group_name(
         self.service_name, self.cluster_name, None)
     # setup test response resources
     self.missing_properties_appspec = files.create_file('appspec_bad.yaml',
                                                         self.BAD_APPSPEC,
                                                         mode='w')
     self.task_definition_arn = \
         'arn:aws:ecs::1234567890:task-definition\\test:2'
     self.deployment_id = 'd-1234567XX'
     self.mock_deployer = CodeDeployer(None, self.APPSPEC_DICT)
     self.mock_deployer.update_task_def_arn(self.task_definition_arn)
     self.expected_stdout = ("Successfully registered new ECS task "
                             "definition " + self.task_definition_arn + "\n"
                             "Successfully created deployment " +
                             self.deployment_id + "\n"
                             "Waiting for " + self.deployment_id +
                             " to succeed...\nSuccessfully deployed " +
                             self.task_definition_arn + " to service '" +
                             self.service_name + "'\n")
Ejemplo n.º 7
0
class TestDeployCommand(BaseAWSCommandParamsTest):

    PREFIX = 'ecs deploy '

    TASK_DEFINITION_JSON = {
        "family": "test",
        "containerDefinitions": [],
        "cpu": "256",
        "memory": '512'
    }

    JSON_APPSPEC = """
    {
        "version": 0.0,
        "resources": [{
            "TestService": {
                "type": "AWS::ECS::Service",
                "properties": {
                    "taskDefinition": "arn:aws:ecs::123:task-definition:1",
                    "loadBalancerInfo": {
                        "containerName": "web",
                        "containerPort": 80
                    }
                }
            }
        }]
    }
    """

    BAD_APPSPEC = """
    version: 0.0
    resources:
      - TestService:
          type: AWS::Lambda::Function
          properties:
            name: myFunction
    """

    YAML_APPSPEC = """
    version: 0.0
    resources:
      - TestService:
          type: AWS::ECS::Service
          properties:
            taskDefinition: arn:aws:ecs::123:task-definition:1
            loadBalancerInfo:
              containerName: web
              containerPort: 80
    """

    APPSPEC_DICT = {
        "version":
        0.0,
        "resources": [{
            "TestService": {
                "type": "AWS::ECS::Service",
                "properties": {
                    "taskDefinition": "arn:aws:ecs::123:task-definition:1",
                    "loadBalancerInfo": {
                        "containerName": "web",
                        "containerPort": 80
                    }
                }
            }
        }]
    }

    def setUp(self):
        super(TestDeployCommand, self).setUp()
        # setup required values
        files = FileCreator()
        self.task_def_file = files.create_file('taskDef.json',
                                               json.dumps(
                                                   self.TASK_DEFINITION_JSON),
                                               mode='w')
        self.appspec_file = files.create_file('appspec.yaml',
                                              self.YAML_APPSPEC,
                                              mode='w')
        self.appspec_file_json = files.create_file('appspec.json',
                                                   self.JSON_APPSPEC,
                                                   mode='w')
        self.service_name = 'serviceTest'
        self.service_arn = 'arn:aws:ecs:::service/serviceTest'
        # setup default optional values
        self.cluster_name = 'default'
        self.cluster_arn = 'arn:aws:ecs:::cluster/default'
        self.application_name = get_app_name(self.service_name,
                                             self.cluster_name, None)
        self.deployment_group_name = get_deploy_group_name(
            self.service_name, self.cluster_name, None)
        # setup test response resources
        self.missing_properties_appspec = files.create_file('appspec_bad.yaml',
                                                            self.BAD_APPSPEC,
                                                            mode='w')
        self.task_definition_arn = \
            'arn:aws:ecs::1234567890:task-definition\\test:2'
        self.deployment_id = 'd-1234567XX'
        self.mock_deployer = CodeDeployer(None, self.APPSPEC_DICT)
        self.mock_deployer.update_task_def_arn(self.task_definition_arn)
        self.expected_stdout = ("Successfully registered new ECS task "
                                "definition " + self.task_definition_arn + "\n"
                                "Successfully created deployment " +
                                self.deployment_id + "\n"
                                "Waiting for " + self.deployment_id +
                                " to succeed...")

    def tearDown(self):
        super(TestDeployCommand, self).tearDown()

    def test_deploy_with_defaults(self):
        cmdline = self.PREFIX
        cmdline += '--service ' + self.service_name
        cmdline += ' --task-definition ' + self.task_def_file
        cmdline += ' --codedeploy-appspec ' + self.appspec_file

        expected_create_deployment_params = \
            self.mock_deployer._get_create_deploy_request(
                self.application_name, self.deployment_group_name)

        self.parsed_responses = self._get_parsed_responses(
            self.cluster_name, self.application_name,
            self.deployment_group_name)

        expected_params = self._get_expected_params(
            self.service_name, self.cluster_name, self.application_name,
            self.deployment_group_name, expected_create_deployment_params)

        stdout, _, _ = self.assert_params_list_for_cmd(cmdline,
                                                       expected_params, None)

        self.assertEqual(stdout, self.expected_stdout)

    def test_deploy_with_default_arns(self):
        cmdline = self.PREFIX
        cmdline += '--service ' + self.service_arn
        cmdline += ' --cluster ' + self.cluster_arn
        cmdline += ' --task-definition ' + self.task_def_file
        cmdline += ' --codedeploy-appspec ' + self.appspec_file

        expected_create_deployment_params = \
            self.mock_deployer._get_create_deploy_request(
                self.application_name, self.deployment_group_name)

        self.parsed_responses = self._get_parsed_responses(
            self.cluster_name, self.application_name,
            self.deployment_group_name)

        expected_params = self._get_expected_params(
            self.service_arn, self.cluster_arn, self.application_name,
            self.deployment_group_name, expected_create_deployment_params)

        stdout, _, _ = self.assert_params_list_for_cmd(cmdline,
                                                       expected_params, None)

        self.assertEqual(stdout, self.expected_stdout)

    def test_deploy_with_json_appspec(self):
        cmdline = self.PREFIX
        cmdline += '--service ' + self.service_name
        cmdline += ' --task-definition ' + self.task_def_file
        cmdline += ' --codedeploy-appspec ' + self.appspec_file_json

        expected_create_deployment_params = \
            self.mock_deployer._get_create_deploy_request(
                self.application_name, self.deployment_group_name)

        self.parsed_responses = self._get_parsed_responses(
            self.cluster_name, self.application_name,
            self.deployment_group_name)

        expected_params = self._get_expected_params(
            self.service_name, self.cluster_name, self.application_name,
            self.deployment_group_name, expected_create_deployment_params)

        stdout, _, _ = self.assert_params_list_for_cmd(cmdline,
                                                       expected_params, None)

        self.assertEqual(stdout, self.expected_stdout)

    def test_deploy_with_optional_values(self):
        custom_app = 'myOtherApp'
        custom_dgp = 'myOtherDgp'
        custom_cluster = 'myOtherCluster'

        cmdline = self.PREFIX
        cmdline += '--service ' + self.service_name
        cmdline += ' --task-definition ' + self.task_def_file
        cmdline += ' --codedeploy-appspec ' + self.appspec_file
        cmdline += ' --cluster ' + self.cluster_name
        cmdline += ' --codedeploy-application ' + custom_app
        cmdline += ' --codedeploy-deployment-group ' + custom_dgp
        cmdline += ' --cluster ' + custom_cluster

        expected_create_deployment_params = \
            self.mock_deployer._get_create_deploy_request(
                custom_app, custom_dgp)

        self.parsed_responses = self._get_parsed_responses(
            custom_cluster, custom_app, custom_dgp)

        expected_params = self._get_expected_params(
            self.service_name, custom_cluster, custom_app, custom_dgp,
            expected_create_deployment_params)

        stdout, _, _ = self.assert_params_list_for_cmd(cmdline,
                                                       expected_params, None)

        self.assertEqual(stdout, self.expected_stdout)

    def test_deploy_error_missing_appspec_property(self):
        cmdline = self.PREFIX
        cmdline += '--service ' + self.service_name
        cmdline += ' --task-definition ' + self.task_def_file
        cmdline += ' --codedeploy-appspec ' + self.missing_properties_appspec

        self.parsed_responses = [{
            'services': [{
                'serviceArn':
                self.service_arn,
                'serviceName':
                self.service_name,
                'clusterArn':
                'arn:aws:ecs:::cluster/' + self.cluster_name
            }]
        }, {
            'application': {
                'applicationId': '876uyh6-45tdfg',
                'applicationName': self.application_name,
                'computePlatform': 'ECS'
            }
        }, {
            'deploymentGroupInfo': {
                'applicationName':
                self.application_name,
                'deploymentGroupName':
                self.deployment_group_name,
                'computePlatform':
                'ECS',
                'ecsServices': [{
                    'serviceName': self.service_name,
                    'clusterName': self.cluster_name
                }]
            }
        }, {
            'taskDefinition': {
                'taskDefinitionArn': self.task_definition_arn,
                'family': 'test',
                'containerDefinitions': []
            }
        }]

        expected_params = [{
            'operation': 'DescribeServices',
            'params': {
                'cluster': self.cluster_name,
                'services': [self.service_name]
            }
        }, {
            'operation': 'GetApplication',
            'params': {
                'applicationName': self.application_name
            }
        }, {
            'operation': 'GetDeploymentGroup',
            'params': {
                'applicationName': self.application_name,
                'deploymentGroupName': self.deployment_group_name
            }
        }, {
            'operation': 'RegisterTaskDefinition',
            'params': self.TASK_DEFINITION_JSON
        }]

        expected_stdout = ("Successfully registered new ECS task "
                           "definition " + self.task_definition_arn + "\n")

        expected_stderr = ("\nError: Resource 'properties' must "
                           "include property 'taskDefinition'\n")

        stdout, stderr, _ = self.assert_params_list_for_cmd(
            cmdline, expected_params, 255)

        self.assertEqual(stdout, expected_stdout)
        self.assertEqual(stderr, expected_stderr)

    def test_deploy_error_invalid_platform(self):
        cmdline = self.PREFIX
        cmdline += '--service ' + self.service_name
        cmdline += ' --task-definition ' + self.task_def_file
        cmdline += ' --codedeploy-appspec ' + self.missing_properties_appspec

        self.parsed_responses = [{
            'services': [{
                'serviceArn':
                self.service_arn,
                'serviceName':
                self.service_name,
                'clusterArn':
                'arn:aws:ecs:::cluster/' + self.cluster_name
            }]
        }, {
            'application': {
                'applicationId': '876uyh6-45tdfg',
                'applicationName': self.application_name,
                'computePlatform': 'Server'
            }
        }, {
            'deploymentGroupInfo': {
                'applicationName':
                self.application_name,
                'deploymentGroupName':
                self.deployment_group_name,
                'computePlatform':
                'ECS',
                'ecsServices': [{
                    'serviceName': self.service_name,
                    'clusterName': self.cluster_name
                }]
            }
        }]

        expected_params = [{
            'operation': 'DescribeServices',
            'params': {
                'cluster': self.cluster_name,
                'services': [self.service_name]
            }
        }, {
            'operation': 'GetApplication',
            'params': {
                'applicationName': self.application_name
            }
        }, {
            'operation': 'GetDeploymentGroup',
            'params': {
                'applicationName': self.application_name,
                'deploymentGroupName': self.deployment_group_name
            }
        }]

        expected_stderr = ("\nError: Application '" + self.application_name +
                           "' must support 'ECS' compute platform\n")

        stdout, stderr, _ = self.assert_params_list_for_cmd(
            cmdline, expected_params, 255)

        self.assertEqual('', stdout)
        self.assertEqual(expected_stderr, stderr)

    def assert_params_list_for_cmd(self,
                                   cmd,
                                   params,
                                   expected_rc=0,
                                   stderr_contains=None):
        stdout, stderr, rc = self.run_cmd(cmd, expected_rc)
        if stderr_contains is not None:
            self.assertIn(stderr_contains, stderr)

        self.assertEqual(len(self.operations_called), len(params))
        for i, param in enumerate(params):
            self.assertEqual(self.operations_called[i][0].name,
                             param['operation'])
            self.assertEqual(self.operations_called[i][1], param['params'])

        return stdout, stderr, rc

    def _get_expected_params(self, service_name, cluster_name, app_name,
                             dgp_name, create_deployment_params):
        return [{
            'operation': 'DescribeServices',
            'params': {
                'cluster': cluster_name,
                'services': [service_name]
            }
        }, {
            'operation': 'GetApplication',
            'params': {
                'applicationName': app_name
            }
        }, {
            'operation': 'GetDeploymentGroup',
            'params': {
                'applicationName': app_name,
                'deploymentGroupName': dgp_name
            }
        }, {
            'operation': 'RegisterTaskDefinition',
            'params': self.TASK_DEFINITION_JSON
        }, {
            'operation': 'CreateDeployment',
            'params': create_deployment_params
        }, {
            'operation': 'GetDeployment',
            'params': {
                'deploymentId': self.deployment_id
            }
        }]

    def _get_parsed_responses(self, cluster_name, app_name, dgp_name):
        return [{
            'services': [{
                'serviceArn': self.service_arn,
                'serviceName': self.service_name,
                'clusterArn': 'arn:aws:ecs:::cluster/' + cluster_name
            }]
        }, {
            'application': {
                'applicationId': '876uyh6-45tdfg',
                'applicationName': app_name,
                'computePlatform': 'ECS'
            }
        }, {
            'deploymentGroupInfo': {
                'applicationName':
                app_name,
                'deploymentGroupName':
                dgp_name,
                'computePlatform':
                'ECS',
                'ecsServices': [{
                    'serviceName': self.service_name,
                    'clusterName': cluster_name
                }]
            }
        }, {
            'taskDefinition': {
                'taskDefinitionArn': self.task_definition_arn,
                'family': 'test',
                'containerDefinitions': []
            }
        }, {
            'deploymentId': self.deployment_id
        }, {
            'deploymentInfo': {
                'applicationName': app_name,
                'status': 'Succeeded'
            }
        }]
Ejemplo n.º 8
0
class TestDeployCommand(BaseAWSCommandParamsTest):

    PREFIX = 'ecs deploy '

    TASK_DEFINITION_JSON = {
        "family": "test",
        "containerDefinitions": [],
        "cpu": "256",
        "memory": '512'
    }

    JSON_APPSPEC = """
    {
        "version": 0.0,
        "resources": [{
            "TestService": {
                "type": "AWS::ECS::Service",
                "properties": {
                    "taskDefinition": "arn:aws:ecs::123:task-definition:1",
                    "loadBalancerInfo": {
                        "containerName": "web",
                        "containerPort": 80
                    }
                }
            }
        }]
    }
    """

    BAD_APPSPEC = """
    version: 0.0
    resources:
      - TestService:
          type: AWS::Lambda::Function
          properties:
            name: myFunction
    """

    YAML_APPSPEC = """
    version: 0.0
    resources:
      - TestService:
          type: AWS::ECS::Service
          properties:
            taskDefinition: arn:aws:ecs::123:task-definition:1
            loadBalancerInfo:
              containerName: web
              containerPort: 80
    """

    APPSPEC_DICT = {
        "version": 0.0,
        "resources": [{
            "TestService": {
                "type": "AWS::ECS::Service",
                "properties": {
                    "taskDefinition": "arn:aws:ecs::123:task-definition:1",
                    "loadBalancerInfo": {
                        "containerName": "web",
                        "containerPort": 80
                    }
                }
            }
        }]
    }

    def setUp(self):
        super(TestDeployCommand, self).setUp()
        # setup required values
        files = FileCreator()
        self.task_def_file = files.create_file(
            'taskDef.json', json.dumps(self.TASK_DEFINITION_JSON), mode='w')
        self.appspec_file = files.create_file(
            'appspec.yaml', self.YAML_APPSPEC, mode='w')
        self.appspec_file_json = files.create_file(
            'appspec.json', self.JSON_APPSPEC, mode='w')
        self.service_name = 'serviceTest'
        self.service_arn = 'arn:aws:ecs:::service/serviceTest'
        # setup default optional values
        self.cluster_name = 'default'
        self.cluster_arn = 'arn:aws:ecs:::cluster/default'
        self.application_name = get_app_name(
            self.service_name, self.cluster_name, None)
        self.deployment_group_name = get_deploy_group_name(
            self.service_name, self.cluster_name, None)
        # setup test response resources
        self.missing_properties_appspec = files.create_file(
            'appspec_bad.yaml', self.BAD_APPSPEC, mode='w')
        self.task_definition_arn = \
            'arn:aws:ecs::1234567890:task-definition\\test:2'
        self.deployment_id = 'd-1234567XX'
        self.mock_deployer = CodeDeployer(None, self.APPSPEC_DICT)
        self.mock_deployer.update_task_def_arn(self.task_definition_arn)
        self.expected_stdout = ("Successfully registered new ECS task "
                                "definition " + self.task_definition_arn + "\n"
                                "Successfully created deployment " +
                                self.deployment_id + "\n"
                                "Waiting for " + self.deployment_id +
                                " to succeed...\nSuccessfully deployed "
                                + self.task_definition_arn + " to service '"
                                + self.service_name + "'\n")

    def tearDown(self):
        super(TestDeployCommand, self).tearDown()

    def test_deploy_with_defaults(self):
        cmdline = self.PREFIX
        cmdline += '--service ' + self.service_name
        cmdline += ' --task-definition ' + self.task_def_file
        cmdline += ' --codedeploy-appspec ' + self.appspec_file

        expected_create_deployment_params = \
            self.mock_deployer._get_create_deploy_request(
                self.application_name, self.deployment_group_name)

        self.parsed_responses = self._get_parsed_responses(
                                    self.cluster_name,
                                    self.application_name,
                                    self.deployment_group_name)

        expected_params = self._get_expected_params(
                                    self.service_name,
                                    self.cluster_name,
                                    self.application_name,
                                    self.deployment_group_name,
                                    expected_create_deployment_params)

        stdout, _, _ = self.assert_params_list_for_cmd(
            cmdline, expected_params, None)

        self.assertEqual(stdout, self.expected_stdout)

    def test_deploy_with_default_arns(self):
        cmdline = self.PREFIX
        cmdline += '--service ' + self.service_arn
        cmdline += ' --cluster ' + self.cluster_arn
        cmdline += ' --task-definition ' + self.task_def_file
        cmdline += ' --codedeploy-appspec ' + self.appspec_file

        expected_create_deployment_params = \
            self.mock_deployer._get_create_deploy_request(
                self.application_name, self.deployment_group_name)

        self.parsed_responses = self._get_parsed_responses(
                                    self.cluster_name,
                                    self.application_name,
                                    self.deployment_group_name)

        expected_params = self._get_expected_params(
                                    self.service_arn,
                                    self.cluster_arn,
                                    self.application_name,
                                    self.deployment_group_name,
                                    expected_create_deployment_params)

        stdout, _, _ = self.assert_params_list_for_cmd(
            cmdline, expected_params, None)

        self.assertEqual(stdout, self.expected_stdout)

    def test_deploy_with_json_appspec(self):
        cmdline = self.PREFIX
        cmdline += '--service ' + self.service_name
        cmdline += ' --task-definition ' + self.task_def_file
        cmdline += ' --codedeploy-appspec ' + self.appspec_file_json

        expected_create_deployment_params = \
            self.mock_deployer._get_create_deploy_request(
                self.application_name, self.deployment_group_name)

        self.parsed_responses = self._get_parsed_responses(
                                    self.cluster_name,
                                    self.application_name,
                                    self.deployment_group_name)

        expected_params = self._get_expected_params(
                                    self.service_name,
                                    self.cluster_name,
                                    self.application_name,
                                    self.deployment_group_name,
                                    expected_create_deployment_params)

        stdout, _, _ = self.assert_params_list_for_cmd(
            cmdline, expected_params, None)

        self.assertEqual(stdout, self.expected_stdout)

    def test_deploy_with_optional_values(self):
        custom_app = 'myOtherApp'
        custom_dgp = 'myOtherDgp'
        custom_cluster = 'myOtherCluster'

        cmdline = self.PREFIX
        cmdline += '--service ' + self.service_name
        cmdline += ' --task-definition ' + self.task_def_file
        cmdline += ' --codedeploy-appspec ' + self.appspec_file
        cmdline += ' --cluster ' + self.cluster_name
        cmdline += ' --codedeploy-application ' + custom_app
        cmdline += ' --codedeploy-deployment-group ' + custom_dgp
        cmdline += ' --cluster ' + custom_cluster

        expected_create_deployment_params = \
            self.mock_deployer._get_create_deploy_request(
                custom_app, custom_dgp)

        self.parsed_responses = self._get_parsed_responses(
            custom_cluster, custom_app, custom_dgp)

        expected_params = self._get_expected_params(
            self.service_name, custom_cluster, custom_app,
            custom_dgp, expected_create_deployment_params)

        stdout, _, _ = self.assert_params_list_for_cmd(
            cmdline, expected_params, None)

        self.assertEqual(stdout, self.expected_stdout)

    def test_deploy_error_missing_appspec_property(self):
        cmdline = self.PREFIX
        cmdline += '--service ' + self.service_name
        cmdline += ' --task-definition ' + self.task_def_file
        cmdline += ' --codedeploy-appspec ' + self.missing_properties_appspec

        self.parsed_responses = [
            {
                'services': [{
                    'serviceArn': self.service_arn,
                    'serviceName': self.service_name,
                    'clusterArn': 'arn:aws:ecs:::cluster/' + self.cluster_name
                }]
            },
            {
                'application': {
                    'applicationId': '876uyh6-45tdfg',
                    'applicationName': self.application_name,
                    'computePlatform': 'ECS'
                }
            },
            {
                'deploymentGroupInfo': {
                    'applicationName': self.application_name,
                    'deploymentGroupName': self.deployment_group_name,
                    'computePlatform': 'ECS',
                    'ecsServices': [{
                        'serviceName': self.service_name,
                        'clusterName': self.cluster_name
                    }]
                }
            },
            {
                'taskDefinition': {
                    'taskDefinitionArn': self.task_definition_arn,
                    'family': 'test',
                    'containerDefinitions': []
                }
            }
        ]

        expected_params = [
            {
                'operation': 'DescribeServices',
                'params': {
                    'cluster': self.cluster_name,
                    'services': [self.service_name]
                }
            },
            {
                'operation': 'GetApplication',
                'params': {'applicationName': self.application_name}
            },
            {
                'operation': 'GetDeploymentGroup',
                'params': {
                    'applicationName': self.application_name,
                    'deploymentGroupName': self.deployment_group_name
                }
            },
            {
                'operation': 'RegisterTaskDefinition',
                'params': self.TASK_DEFINITION_JSON
            }
        ]

        expected_stdout = ("Successfully registered new ECS task "
                           "definition " + self.task_definition_arn + "\n")

        expected_stderr = ("\nError: Resource 'properties' must "
                           "include property 'taskDefinition'\n")

        stdout, stderr, _ = self.assert_params_list_for_cmd(
            cmdline, expected_params, 255)

        self.assertEqual(stdout, expected_stdout)
        self.assertEqual(stderr, expected_stderr)

    def test_deploy_error_invalid_platform(self):
        cmdline = self.PREFIX
        cmdline += '--service ' + self.service_name
        cmdline += ' --task-definition ' + self.task_def_file
        cmdline += ' --codedeploy-appspec ' + self.missing_properties_appspec

        self.parsed_responses = [
            {
                'services': [{
                    'serviceArn': self.service_arn,
                    'serviceName': self.service_name,
                    'clusterArn': 'arn:aws:ecs:::cluster/' + self.cluster_name
                }]
            },
            {
                'application': {
                    'applicationId': '876uyh6-45tdfg',
                    'applicationName': self.application_name,
                    'computePlatform': 'Server'
                }
            },
            {
                'deploymentGroupInfo': {
                    'applicationName': self.application_name,
                    'deploymentGroupName': self.deployment_group_name,
                    'computePlatform': 'ECS',
                    'ecsServices': [{
                        'serviceName': self.service_name,
                        'clusterName': self.cluster_name
                    }]
                }
            }
        ]

        expected_params = [
            {
                'operation': 'DescribeServices',
                'params': {
                    'cluster': self.cluster_name,
                    'services': [self.service_name]
                }
            },
            {
                'operation': 'GetApplication',
                'params': {'applicationName': self.application_name}
            },
            {
                'operation': 'GetDeploymentGroup',
                'params': {
                    'applicationName': self.application_name,
                    'deploymentGroupName': self.deployment_group_name
                }
            }
        ]

        expected_stderr = ("\nError: Application '" + self.application_name +
                           "' must support 'ECS' compute platform\n")

        stdout, stderr, _ = self.assert_params_list_for_cmd(
            cmdline, expected_params, 255)

        self.assertEqual('', stdout)
        self.assertEqual(expected_stderr, stderr)

    def assert_params_list_for_cmd(self, cmd, params, expected_rc=0,
                                   stderr_contains=None):
        stdout, stderr, rc = self.run_cmd(cmd, expected_rc)
        if stderr_contains is not None:
            self.assertIn(stderr_contains, stderr)

        self.assertEqual(len(self.operations_called), len(params))
        for i, param in enumerate(params):
            self.assertEqual(
                self.operations_called[i][0].name, param['operation'])
            self.assertEqual(
                self.operations_called[i][1], param['params'])

        return stdout, stderr, rc

    def _get_expected_params(self, service_name, cluster_name, app_name,
                             dgp_name, create_deployment_params):
        return [
            {
                'operation': 'DescribeServices',
                'params': {
                    'cluster': cluster_name,
                    'services': [service_name]
                }
            },
            {
                'operation': 'GetApplication',
                'params': {'applicationName': app_name}
            },
            {
                'operation': 'GetDeploymentGroup',
                'params': {
                    'applicationName': app_name,
                    'deploymentGroupName': dgp_name
                }
            },
            {
                'operation': 'RegisterTaskDefinition',
                'params': self.TASK_DEFINITION_JSON
            },
            {
                'operation': 'CreateDeployment',
                'params': create_deployment_params
            },
            {
                'operation': 'GetDeployment',
                'params': {
                    'deploymentId': self.deployment_id
                }
            }
        ]

    def _get_parsed_responses(self, cluster_name, app_name, dgp_name):
        return [
            {
                'services': [{
                    'serviceArn': self.service_arn,
                    'serviceName': self.service_name,
                    'clusterArn': 'arn:aws:ecs:::cluster/' + cluster_name
                }]
            },
            {
                'application': {
                    'applicationId': '876uyh6-45tdfg',
                    'applicationName': app_name,
                    'computePlatform': 'ECS'
                }
            },
            {
                'deploymentGroupInfo': {
                    'applicationName': app_name,
                    'deploymentGroupName': dgp_name,
                    'computePlatform': 'ECS',
                    'ecsServices': [{
                        'serviceName': self.service_name,
                        'clusterName': cluster_name
                    }]
                }
            },
            {
                'taskDefinition': {
                    'taskDefinitionArn': self.task_definition_arn,
                    'family': 'test',
                    'containerDefinitions': []
                }
            },
            {
                'deploymentId': self.deployment_id
            },
            {
                'deploymentInfo': {
                    'applicationName': app_name,
                    'status': 'Succeeded'
                }
            }
        ]
Ejemplo n.º 9
0
 def setUp(self):
     self.deployer = CodeDeployer(None, self.TEST_APPSPEC)
Ejemplo n.º 10
0
class TestCodeDeployer(unittest.TestCase):
    TEST_APPSPEC = {
        "version":
        0.0,
        "resources": [{
            "TestService": {
                "type": "AWS::ECS::Service",
                "properties": {
                    "taskDefinition": "arn:aws:ecs:::task-definition/test:1",
                    "loadBalancerInfo": {
                        "containerName": "web",
                        "containerPort": 80
                    }
                }
            }
        }]
    }

    def setUp(self):
        self.deployer = CodeDeployer(None, self.TEST_APPSPEC)

    def test_update_task_def_arn(self):
        test_arn = 'arn:aws:ecs::1234567890:task-definition/new-thing:3'
        self.deployer.update_task_def_arn(test_arn)

        appspec_resources = self.deployer._appspec_dict['resources']
        for resource in appspec_resources:
            actual_arn = \
                resource['TestService']['properties']['taskDefinition']
            self.assertEqual(actual_arn, test_arn)

    def test_update_task_def_arn_error_required_key(self):
        invalid_appspec = {
            "version":
            0.0,
            "resources": [{
                "TestFunc": {
                    "type": "AWS::Lambda::Function",
                    "properties": {
                        "name": "some-function"
                    }
                }
            }]
        }
        bad_deployer = CodeDeployer(None, invalid_appspec)

        with self.assertRaises(MissingPropertyError):
            bad_deployer.update_task_def_arn('arn:aws:ecs:task-definiton/test')

    def test_get_create_deploy_request(self):
        test_app = 'test-application'
        test_dgp = 'test-deployment-group'
        request = self.deployer._get_create_deploy_request(test_app, test_dgp)

        self.assertEqual(request['applicationName'], test_app)
        self.assertEqual(request['deploymentGroupName'], test_dgp)

        actual_appspec = \
            json.loads(request['revision']['appSpecContent']['content'])
        actual_hash = request['revision']['appSpecContent']['sha256']

        self.assertEqual(actual_appspec, self.deployer._appspec_dict)
        self.assertEqual(actual_hash, self.deployer._get_appspec_hash())

    def test_get_appspec_hash(self):
        appspec_str = json.dumps(self.deployer._appspec_dict)
        encoded_appspec = compat.ensure_bytes(appspec_str)
        expected_hash = hashlib.sha256(encoded_appspec).hexdigest()

        actual_hash = self.deployer._get_appspec_hash()
        self.assertEqual(actual_hash, expected_hash)
Ejemplo n.º 11
0
 def setUp(self):
     self.deployer = CodeDeployer(None, self.TEST_APPSPEC)
Ejemplo n.º 12
0
class TestCodeDeployer(unittest.TestCase):
    TEST_APPSPEC = {
        "version": 0.0,
        "resources": [{
            "TestService": {
                "type": "AWS::ECS::Service",
                "properties": {
                    "taskDefinition": "arn:aws:ecs:::task-definition/test:1",
                    "loadBalancerInfo": {
                        "containerName": "web",
                        "containerPort": 80
                    }
                }
            }
        }]
    }

    def setUp(self):
        self.deployer = CodeDeployer(None, self.TEST_APPSPEC)

    def test_update_task_def_arn(self):
        test_arn = 'arn:aws:ecs::1234567890:task-definition/new-thing:3'
        self.deployer.update_task_def_arn(test_arn)

        appspec_resources = self.deployer._appspec_dict['resources']
        for resource in appspec_resources:
            actual_arn = \
                resource['TestService']['properties']['taskDefinition']
            self.assertEqual(actual_arn, test_arn)

    def test_update_task_def_arn_error_required_key(self):
        invalid_appspec = {
            "version": 0.0,
            "resources": [{
                "TestFunc": {
                    "type": "AWS::Lambda::Function",
                    "properties": {
                        "name": "some-function"
                    }
                }
            }]
        }
        bad_deployer = CodeDeployer(None, invalid_appspec)

        with self.assertRaises(MissingPropertyError):
            bad_deployer.update_task_def_arn('arn:aws:ecs:task-definiton/test')

    def test_get_create_deploy_request(self):
        test_app = 'test-application'
        test_dgp = 'test-deployment-group'
        request = self.deployer._get_create_deploy_request(test_app, test_dgp)

        self.assertEqual(request['applicationName'], test_app)
        self.assertEqual(request['deploymentGroupName'], test_dgp)

        actual_appspec = \
            json.loads(request['revision']['appSpecContent']['content'])
        actual_hash = request['revision']['appSpecContent']['sha256']

        self.assertEqual(actual_appspec, self.deployer._appspec_dict)
        self.assertEqual(actual_hash, self.deployer._get_appspec_hash())

    def test_get_appspec_hash(self):
        appspec_str = json.dumps(self.deployer._appspec_dict)
        encoded_appspec = compat.ensure_bytes(appspec_str)
        expected_hash = hashlib.sha256(encoded_appspec).hexdigest()

        actual_hash = self.deployer._get_appspec_hash()
        self.assertEqual(actual_hash, expected_hash)
Ejemplo n.º 13
0
class TestCodeDeployer(unittest.TestCase):
    TEST_APPSPEC = {
        "version": 0.0,
        "resources": [{
            "TestService": {
                "type": "AWS::ECS::Service",
                "properties": {
                    "taskDefinition": "arn:aws:ecs:::task-definition/test:1",
                    "loadBalancerInfo": {
                        "containerName": "web",
                        "containerPort": 80
                    }
                }
            }
        }]
    }

    def setUp(self):
        waiter = mock.Mock()
        waiter.wait.return_value = {}
        mock_cd = mock.Mock()
        mock_cd.get_waiter.return_value = waiter

        self.deployer = CodeDeployer(mock_cd, self.TEST_APPSPEC)

    def test_update_task_def_arn(self):
        test_arn = 'arn:aws:ecs::1234567890:task-definition/new-thing:3'
        self.deployer.update_task_def_arn(test_arn)

        appspec_resources = self.deployer._appspec_dict['resources']
        for resource in appspec_resources:
            actual_arn = \
                resource['TestService']['properties']['taskDefinition']
            self.assertEqual(actual_arn, test_arn)

    def test_update_task_def_arn_error_required_key(self):
        invalid_appspec = {
            "version": 0.0,
            "resources": [{
                "TestFunc": {
                    "type": "AWS::Lambda::Function",
                    "properties": {
                        "name": "some-function"
                    }
                }
            }]
        }
        bad_deployer = CodeDeployer(None, invalid_appspec)

        with self.assertRaises(MissingPropertyError):
            bad_deployer.update_task_def_arn('arn:aws:ecs:task-definiton/test')

    def test_get_create_deploy_request(self):
        test_app = 'test-application'
        test_dgp = 'test-deployment-group'
        request = self.deployer._get_create_deploy_request(test_app, test_dgp)

        self.assertEqual(request['applicationName'], test_app)
        self.assertEqual(request['deploymentGroupName'], test_dgp)

        actual_appspec = \
            json.loads(request['revision']['appSpecContent']['content'])
        actual_hash = request['revision']['appSpecContent']['sha256']

        self.assertEqual(actual_appspec, self.deployer._appspec_dict)
        self.assertEqual(actual_hash, self.deployer._get_appspec_hash())

    def test_get_appspec_hash(self):
        appspec_str = json.dumps(self.deployer._appspec_dict)
        encoded_appspec = compat.ensure_bytes(appspec_str)
        expected_hash = hashlib.sha256(encoded_appspec).hexdigest()

        actual_hash = self.deployer._get_appspec_hash()
        self.assertEqual(actual_hash, expected_hash)

    def test_wait_for_deploy_success_default_wait(self):
        mock_id = 'd-1234567XX'
        expected_stdout = self.deployer.MSG_WAITING.format(
            deployment_id=mock_id, wait=30)

        with capture_output() as captured:
            self.deployer.wait_for_deploy_success('d-1234567XX', 0)
            self.assertEqual(expected_stdout, captured.stdout.getvalue())

    def test_wait_for_deploy_success_custom_wait(self):
        mock_id = 'd-1234567XX'
        mock_wait = 40

        expected_stdout = self.deployer.MSG_WAITING.format(
            deployment_id=mock_id, wait=mock_wait)

        with capture_output() as captured:
            self.deployer.wait_for_deploy_success('d-1234567XX', mock_wait)
            self.assertEqual(expected_stdout, captured.stdout.getvalue())

    def test_wait_for_deploy_success_max_wait_exceeded(self):
        mock_id = 'd-1234567XX'
        mock_wait = MAX_WAIT_MIN + 15

        expected_stdout = self.deployer.MSG_WAITING.format(
            deployment_id=mock_id, wait=MAX_WAIT_MIN)

        with capture_output() as captured:
            self.deployer.wait_for_deploy_success('d-1234567XX', mock_wait)
            self.assertEqual(expected_stdout, captured.stdout.getvalue())
Ejemplo n.º 14
0
class TestCodeDeployer(unittest.TestCase):
    TEST_APPSPEC = {
        "version":
        0.0,
        "resources": [{
            "TestService": {
                "type": "AWS::ECS::Service",
                "properties": {
                    "taskDefinition": "arn:aws:ecs:::task-definition/test:1",
                    "loadBalancerInfo": {
                        "containerName": "web",
                        "containerPort": 80
                    }
                }
            }
        }]
    }

    def setUp(self):
        waiter = mock.Mock()
        waiter.wait.return_value = {}
        mock_cd = mock.Mock()
        mock_cd.get_waiter.return_value = waiter

        self.deployer = CodeDeployer(mock_cd, self.TEST_APPSPEC)

    def test_update_task_def_arn(self):
        test_arn = 'arn:aws:ecs::1234567890:task-definition/new-thing:3'
        self.deployer.update_task_def_arn(test_arn)

        appspec_resources = self.deployer._appspec_dict['resources']
        for resource in appspec_resources:
            actual_arn = \
                resource['TestService']['properties']['taskDefinition']
            self.assertEqual(actual_arn, test_arn)

    def test_update_task_def_arn_error_required_key(self):
        invalid_appspec = {
            "version":
            0.0,
            "resources": [{
                "TestFunc": {
                    "type": "AWS::Lambda::Function",
                    "properties": {
                        "name": "some-function"
                    }
                }
            }]
        }
        bad_deployer = CodeDeployer(None, invalid_appspec)

        with self.assertRaises(MissingPropertyError):
            bad_deployer.update_task_def_arn('arn:aws:ecs:task-definiton/test')

    def test_get_create_deploy_request(self):
        test_app = 'test-application'
        test_dgp = 'test-deployment-group'
        request = self.deployer._get_create_deploy_request(test_app, test_dgp)

        self.assertEqual(request['applicationName'], test_app)
        self.assertEqual(request['deploymentGroupName'], test_dgp)

        actual_appspec = \
            json.loads(request['revision']['appSpecContent']['content'])
        actual_hash = request['revision']['appSpecContent']['sha256']

        self.assertEqual(actual_appspec, self.deployer._appspec_dict)
        self.assertEqual(actual_hash, self.deployer._get_appspec_hash())

    def test_get_appspec_hash(self):
        appspec_str = json.dumps(self.deployer._appspec_dict)
        encoded_appspec = compat.ensure_bytes(appspec_str)
        expected_hash = hashlib.sha256(encoded_appspec).hexdigest()

        actual_hash = self.deployer._get_appspec_hash()
        self.assertEqual(actual_hash, expected_hash)

    def test_wait_for_deploy_success_default_wait(self):
        mock_id = 'd-1234567XX'
        expected_stdout = self.deployer.MSG_WAITING.format(
            deployment_id=mock_id, wait=30)

        with capture_output() as captured:
            self.deployer.wait_for_deploy_success('d-1234567XX', 0)
            self.assertEqual(expected_stdout, captured.stdout.getvalue())

    def test_wait_for_deploy_success_custom_wait(self):
        mock_id = 'd-1234567XX'
        mock_wait = 40

        expected_stdout = self.deployer.MSG_WAITING.format(
            deployment_id=mock_id, wait=mock_wait)

        with capture_output() as captured:
            self.deployer.wait_for_deploy_success('d-1234567XX', mock_wait)
            self.assertEqual(expected_stdout, captured.stdout.getvalue())

    def test_wait_for_deploy_success_max_wait_exceeded(self):
        mock_id = 'd-1234567XX'
        mock_wait = MAX_WAIT_MIN + 15

        expected_stdout = self.deployer.MSG_WAITING.format(
            deployment_id=mock_id, wait=MAX_WAIT_MIN)

        with capture_output() as captured:
            self.deployer.wait_for_deploy_success('d-1234567XX', mock_wait)
            self.assertEqual(expected_stdout, captured.stdout.getvalue())