Beispiel #1
0
def test_resume_with_unknown_upload_id(vcr_fixture, runner, config_file,
                                       config_profile, content_input_file,
                                       test_id):
    object_name = 'a'
    upload_id = 'UNKNOWN_UPLOAD_ID'

    # resume multipart upload
    result = invoke(runner, config_file, config_profile, [
        'object', 'resume-put', '-ns', util.NAMESPACE, '-bn',
        "cli_temp_multipart_bucket_" + test_id, '--name', object_name,
        '--file', content_input_file, '--upload-id', upload_id
    ])
    util.validate_service_error(result, error_message='No such upload')
Beispiel #2
0
def test_put_object_multipart_and_parallel_options(runner, config_file,
                                                   config_profile,
                                                   content_input_file):
    object_name = 'a'

    # validate error is returned if --parallel-upload-count and --disable-parallel-uploads are used
    result = invoke(runner, config_file, config_profile, [
        'object', 'put', '-ns', util.NAMESPACE, '-bn', 'unknown_bucket',
        '--name', object_name, '--file', content_input_file,
        '--parallel-upload-count', '2', '--disable-parallel-uploads'
    ])
    util.validate_service_error(result)

    # validate error is returned if --parallel-upload-count and --no-multipart are used
    result = invoke(runner, config_file, config_profile, [
        'object', 'put', '-ns', util.NAMESPACE, '-bn', 'unknown_bucket',
        '--name', object_name, '--file', content_input_file,
        '--parallel-upload-count', '2', '--no-multipart'
    ])
    util.validate_service_error(result)
Beispiel #3
0
def test_boot_volume_clone_backup(network_resources):
    with test_config_container.create_vcr(cassette_library_dir=CASSETTE_LIBRARY_DIR).use_cassette('boot_volume_test_boot_volume_clone_backup.yml'):
        boot_volume_id = None
        instance_ocid = None
        backup_boot_volume_id = None
        cloned_boot_volume_id = None
        backup_id = None
        try:
            instance_name = util.random_name('boot_vol_instance')
            image_id = util.oracle_linux_image()
            shape = 'VM.Standard1.1'
            hostname_label = util.random_name('bootvolinst', insert_underscore=False)
            boot_volume_size_in_gbs = '51'

            result = invoke([
                'compute', 'instance', 'launch',
                '--compartment-id', util.COMPARTMENT_ID,
                '--availability-domain', util.availability_domain(),
                '--display-name', instance_name,
                '--subnet-id', network_resources[1],
                '--image-id', image_id,
                '--shape', shape,
                '--hostname-label', hostname_label,
                '--boot-volume-size-in-gbs', boot_volume_size_in_gbs,
                '--wait-for-state', 'RUNNING',
                '--wait-interval-seconds', util.WAIT_INTERVAL_SECONDS
            ])
            util.validate_response(result, json_response_expected=False)
            instance_data = util.get_json_from_mixed_string(result.output)['data']
            instance_ocid = instance_data['id']
            assert 'image' == instance_data['source-details']['source-type']
            assert image_id == instance_data['source-details']['image-id']

            result = invoke([
                'compute', 'boot-volume-attachment', 'list',
                '-c', util.COMPARTMENT_ID,
                '--availability-domain', util.availability_domain(),
                '--instance-id', instance_data['id']
            ])
            util.validate_response(result)
            parsed_result = json.loads(result.output)
            assert len(parsed_result['data']) == 1
            boot_volume_id = parsed_result['data'][0]['boot-volume-id']

            result = invoke([
                'bv', 'boot-volume', 'get',
                '--boot-volume-id', boot_volume_id
            ])
            util.validate_response(result)
            parsed_result = json.loads(result.output)
            boot_volume_size_in_gbs = parsed_result['data']['size-in-gbs']
            assert boot_volume_size_in_gbs == int(boot_volume_size_in_gbs)

            result = invoke([
                'compute', 'instance', 'terminate',
                '--instance-id', instance_ocid,
                '--wait-for-state', 'TERMINATED',
                '--preserve-boot-volume', 'true',
                '--force'
            ])
            util.validate_response(result, json_response_expected=False)
            instance_ocid = None

            # Since we preserved the volume it should still be available
            result = invoke(['bv', 'boot-volume', 'get', '--boot-volume-id', boot_volume_id])
            util.validate_response(result)
            parsed_result = json.loads(result.output)
            assert util.availability_domain() == parsed_result['data']['availability-domain']
            assert 'AVAILABLE' == parsed_result['data']['lifecycle-state']
            assert image_id == parsed_result['data']['image-id']
            size_in_gbs = int(parsed_result['data']['size-in-gbs'])

            new_size_in_gbs = size_in_gbs + 10

            # Resize boot volume to new_size_in_gbs
            result = invoke(['bv', 'boot-volume', 'update', '--boot-volume-id', boot_volume_id,
                             '--size-in-gbs', str(new_size_in_gbs),
                             '--wait-for-state', 'AVAILABLE',
                             '--wait-interval-seconds', util.WAIT_INTERVAL_SECONDS])
            util.validate_response(result, json_response_expected=False)

            # Since we preserved the volume it should still be available
            result = invoke(['bv', 'boot-volume', 'get', '--boot-volume-id', boot_volume_id])
            util.validate_response(result)
            parsed_result = json.loads(result.output)
            assert 'AVAILABLE' == parsed_result['data']['lifecycle-state']
            assert new_size_in_gbs == int(parsed_result['data']['size-in-gbs'])

            # Take a backup
            result = invoke(['bv', 'boot-volume-backup', 'create', '--boot-volume-id', boot_volume_id,
                             '--wait-for-state', 'AVAILABLE',
                             '--wait-interval-seconds', util.WAIT_INTERVAL_SECONDS])
            util.validate_response(result, json_response_expected=False)
            parsed_result = util.get_json_from_mixed_string(result.output)
            assert boot_volume_id == parsed_result['data']['boot-volume-id']
            assert image_id == parsed_result['data']['image-id']
            assert 'AVAILABLE' == parsed_result['data']['lifecycle-state']
            backup_id = parsed_result['data']['id']

            # Boot Volume Create Error cases

            # Error 1: No option specified
            result = invoke(['bv', 'boot-volume', 'create',
                             '--wait-for-state', 'AVAILABLE',
                             '--wait-interval-seconds', util.WAIT_INTERVAL_SECONDS])
            assert "An empty boot volume cannot be created. Please specify either --boot-volume-backup-id, --source-boot-volume-id or --source-volume-replica-id" in result.output

            # Error 2: Both options specified
            result = invoke(['bv', 'boot-volume', 'create',
                             '--source-boot-volume-id', boot_volume_id[0],
                             '--boot-volume-backup-id', boot_volume_id[0],
                             '--wait-for-state', 'AVAILABLE',
                             '--wait-interval-seconds', util.WAIT_INTERVAL_SECONDS])
            assert "You can only specify one of either --source-boot-volume-id, --boot-volume-backup-id or --source-volume-replica-id option" in result.output

            # Clone the boot volume (Error 1: Invalid Boot Volume ID)
            result = invoke(['bv', 'boot-volume', 'create',
                             '--source-boot-volume-id', boot_volume_id[0],
                             '--wait-for-state', 'AVAILABLE',
                             '--wait-interval-seconds', util.WAIT_INTERVAL_SECONDS])
            util.validate_service_error(result, error_message="InvalidParameter")

            backup_policy_ids = get_backup_policy_ids()
            create_new_size_in_gbs = new_size_in_gbs + 10

            # Clone the boot volume with bronze backup policy and larger size
            result = invoke(['bv', 'boot-volume', 'create',
                             '--source-boot-volume-id', boot_volume_id,
                             '--backup-policy-id', backup_policy_ids["bronze"],
                             '--wait-for-state', 'AVAILABLE',
                             '--size-in-gbs', str(create_new_size_in_gbs),
                             '--wait-interval-seconds', util.WAIT_INTERVAL_SECONDS])
            util.validate_response(result, json_response_expected=False)
            parsed_result = util.get_json_from_mixed_string(result.output)
            assert util.availability_domain() == parsed_result['data']['availability-domain']
            assert 'AVAILABLE' == parsed_result['data']['lifecycle-state']
            assert image_id == parsed_result['data']['image-id']
            assert create_new_size_in_gbs == int(parsed_result['data']['size-in-gbs'])
            cloned_boot_volume_id = parsed_result['data']['id']

            # Verify the backup policy
            result = invoke(['bv', 'volume-backup-policy-assignment',
                             'get-volume-backup-policy-asset-assignment',
                             '--asset-id', cloned_boot_volume_id])
            util.validate_response(result)
            parsed_result = json.loads(result.output)
            backup_policy_assignment_id = parsed_result["data"][0]["id"]
            assert parsed_result["data"][0]["policy-id"] == backup_policy_ids["bronze"]

            # Remove backup policy
            result = invoke(['bv', 'volume-backup-policy-assignment',
                             'delete', '--policy-assignment-id', backup_policy_assignment_id, '--force'])
            util.validate_response(result)

            # Change backup policy to silver
            result = invoke(['bv', 'volume-backup-policy-assignment', 'create',
                             '--asset-id', cloned_boot_volume_id,
                             '--policy-id', backup_policy_ids['silver']])
            util.validate_response(result)
            parsed_result = json.loads(result.output)
            backup_policy_assignment_id = parsed_result["data"]["id"]
            assert parsed_result["data"]["policy-id"] == backup_policy_ids["silver"]

            # Remove the backup policy
            result = invoke(['bv', 'volume-backup-policy-assignment',
                             'delete', '--policy-assignment-id', backup_policy_assignment_id, '--force'])
            util.validate_response(result)

            # We can now launch an instance using that boot volume
            result = invoke([
                'compute', 'instance', 'launch',
                '--compartment-id', util.COMPARTMENT_ID,
                '--availability-domain', util.availability_domain(),
                '--display-name', instance_name,
                '--subnet-id', network_resources[1],
                '--shape', shape,
                '--hostname-label', hostname_label,
                '--source-boot-volume-id', cloned_boot_volume_id,
                '--wait-for-state', 'RUNNING',
                '--wait-interval-seconds', util.WAIT_INTERVAL_SECONDS
            ])
            util.validate_response(result, json_response_expected=False)
            instance_data = util.get_json_from_mixed_string(result.output)['data']
            instance_ocid = instance_data['id']
            assert 'bootVolume' == instance_data['source-details']['source-type']
            assert cloned_boot_volume_id == instance_data['source-details']['boot-volume-id']

            clean_up_instances(instance_ocid)
            cloned_boot_volume_id = None
            instance_ocid = None

            # Delete existing boot volume
            clean_up_boot_volume(boot_volume_id)
            boot_volume_id = None

            # Create boot volume from backup (Error 1: Invalid Backup Volume ID)
            result = invoke(['bv', 'boot-volume', 'create',
                             '--boot-volume-backup-id', backup_id[0],
                             '--availability-domain', util.availability_domain(),
                             '--wait-for-state', 'AVAILABLE',
                             '--wait-interval-seconds', util.WAIT_INTERVAL_SECONDS])
            util.validate_service_error(result, error_message="InvalidParameter")

            # Create boot volume from backup (Error 2: Availability domain not specified)
            result = invoke(['bv', 'boot-volume', 'create',
                             '--boot-volume-backup-id', backup_id,
                             '--wait-for-state', 'AVAILABLE',
                             '--wait-interval-seconds', util.WAIT_INTERVAL_SECONDS])
            assert "An availability domain must be specified when restoring a boot volume from backup" in result.output

            # Create boot volume from backup
            result = invoke(['bv', 'boot-volume', 'create',
                             '--boot-volume-backup-id', backup_id,
                             '--availability-domain', util.availability_domain(),
                             '--wait-for-state', 'AVAILABLE',
                             '--wait-interval-seconds', util.WAIT_INTERVAL_SECONDS])
            util.validate_response(result, json_response_expected=False)
            parsed_result = util.get_json_from_mixed_string(result.output)
            assert util.availability_domain() == parsed_result['data']['availability-domain']
            assert 'AVAILABLE' == parsed_result['data']['lifecycle-state']
            assert image_id == parsed_result['data']['image-id']
            backup_boot_volume_id = parsed_result['data']['id']

            # We can now launch an instance using that boot volume
            result = invoke([
                'compute', 'instance', 'launch',
                '--compartment-id', util.COMPARTMENT_ID,
                '--availability-domain', util.availability_domain(),
                '--display-name', instance_name,
                '--subnet-id', network_resources[1],
                '--shape', shape,
                '--hostname-label', hostname_label,
                '--source-boot-volume-id', backup_boot_volume_id,
                '--wait-for-state', 'RUNNING',
                '--wait-interval-seconds', util.WAIT_INTERVAL_SECONDS
            ])
            util.validate_response(result, json_response_expected=False)
            instance_data = util.get_json_from_mixed_string(result.output)['data']
            instance_ocid = instance_data['id']
            assert 'bootVolume' == instance_data['source-details']['source-type']
            assert backup_boot_volume_id == instance_data['source-details']['boot-volume-id']

            clean_up_instances(instance_ocid)
            backup_boot_volume_id = None
            instance_ocid = None

        finally:
            clean_up_instances(instance_ocid)
            clean_up_boot_volume(boot_volume_id)
            clean_up_boot_volume(cloned_boot_volume_id)
            clean_up_boot_volume(backup_boot_volume_id)
            clean_up_boot_volume_backup(backup_id)
Beispiel #4
0
    def subtest_instance_console_connections(self):
        result = self.invoke([
            'compute', 'instance-console-connection', 'create',
            '--instance-id', self.instance_ocid, '--ssh-public-key-file',
            util.SSH_AUTHORIZED_KEYS_FILE
        ])
        util.validate_response(result)

        instance_console_connection_details = json.loads(result.output)
        self.assertIsNotNone(
            instance_console_connection_details['data']['connection-string'])
        self.assertIsNotNone(instance_console_connection_details['data']['id'])
        self.assertIsNotNone(
            instance_console_connection_details['data']['lifecycle-state'])
        self.assertEquals(
            self.instance_ocid,
            instance_console_connection_details['data']['instance-id'])
        self.assertIsNotNone(
            instance_console_connection_details['data']['fingerprint'])

        result = self.invoke([
            'compute', 'instance-console-connection', 'get',
            '--instance-console-connection-id',
            instance_console_connection_details['data']['id']
        ])
        parsed_result = json.loads(result.output)
        self.assertEquals(instance_console_connection_details['data']['id'],
                          parsed_result['data']['id'])
        self.assertEquals(
            instance_console_connection_details['data']['instance-id'],
            parsed_result['data']['instance-id'])
        self.assertEquals(
            instance_console_connection_details['data']['fingerprint'],
            parsed_result['data']['fingerprint'])
        self.assertEquals(
            instance_console_connection_details['data']['compartment-id'],
            parsed_result['data']['compartment-id'])
        self.assertEquals(
            instance_console_connection_details['data']['connection-string'],
            parsed_result['data']['connection-string'])
        self.assertEquals(
            {}, instance_console_connection_details['data']['freeform-tags'])
        self.assertEquals(
            {}, instance_console_connection_details['data']['defined-tags'])
        self.assertIsNotNone(parsed_result['data']['lifecycle-state'])

        private_key_file = 'C:\\Users\\oci\console.ppk'  # noqa: W605
        params = [
            'compute', 'instance-console-connection',
            'get-plink-connection-string', '--instance-console-connection-id',
            instance_console_connection_details['data']['id'],
            '--private-key-file', private_key_file
        ]

        result = self.invoke(params)

        util.validate_response(result, json_response_expected=False)

        m = re.search(
            oci_cli_compute.compute_cli_extended.
            INSTANCE_CONSOLE_CONNECTION_STRING_INTERMEDIATE_HOST_REGEX,
            instance_console_connection_details['data']['connection-string'])
        intermediate_host = m.group(0)

        connection_template = 'Start-Job {{echo N | plink -ssh -N -i "{3}" -P 443 -l {1} {2} -L 5905:{0}:5905}}; sleep 5 ; plink -L 5900:localhost:5900 localhost -P 5905 -N -i "{3}" -l {1}'
        expected_plink_connection_string = connection_template.format(
            instance_console_connection_details['data']['instance-id'],
            instance_console_connection_details['data']['id'],
            intermediate_host, private_key_file)
        assert expected_plink_connection_string == result.output.strip()

        # confirm that error from internal call to GetConsoleConnection returns service error and non-zero status code
        params = [
            'compute', 'instance-console-connection',
            'get-plink-connection-string', '--instance-console-connection-id',
            'fake-instance-console-connection-id', '--private-key-file',
            private_key_file
        ]

        result = self.invoke(params)
        util.validate_service_error(result, error_message='ServiceError')

        keep_paginating = True
        next_page = None
        all_connections = []
        while keep_paginating:
            if next_page:
                result = self.invoke([
                    'compute', 'instance-console-connection', 'list',
                    '--compartment-id', util.COMPARTMENT_ID, '--page',
                    next_page
                ])
            else:
                result = self.invoke([
                    'compute', 'instance-console-connection', 'list',
                    '--compartment-id', util.COMPARTMENT_ID
                ])

            if result.output:
                parsed_result = json.loads(result.output)
                all_connections.extend(parsed_result['data'])
                if 'opc-next-page' in parsed_result:
                    next_page = parsed_result['opc-next-page']
                    keep_paginating = next_page is not None
                else:
                    keep_paginating = False
            else:
                keep_paginating = False

        match_found = False
        for conn in all_connections:
            if conn['id'] == instance_console_connection_details['data']['id']:
                match_found = True
                self.assertEquals(
                    instance_console_connection_details['data']['instance-id'],
                    conn['instance-id'])
                self.assertEquals(
                    instance_console_connection_details['data']['fingerprint'],
                    conn['fingerprint'])
                self.assertEquals(
                    instance_console_connection_details['data']
                    ['compartment-id'], conn['compartment-id'])
                self.assertEquals(
                    instance_console_connection_details['data']
                    ['connection-string'], conn['connection-string'])
                self.assertIsNotNone(conn['lifecycle-state'])
                break

        self.assertTrue(match_found)

        self.invoke([
            'compute', 'instance-console-connection', 'delete',
            '--instance-console-connection-id',
            instance_console_connection_details['data']['id'], '--force'
        ])

        result = self.invoke([
            'compute', 'instance-console-connection', 'get',
            '--instance-console-connection-id',
            instance_console_connection_details['data']['id']
        ])
        parsed_result = json.loads(result.output)
        if 'DELET' not in parsed_result['data']['lifecycle-state']:
            print("parsed_result=" + str(parsed_result) +
                  ", lifecycle-state=" +
                  str(parsed_result['data']['lifecycle-state']))
            util.vcr_mode_aware_sleep(60)
            result = self.invoke([
                'compute', 'instance-console-connection', 'get',
                '--instance-console-connection-id',
                instance_console_connection_details['data']['id']
            ])
            parsed_result = json.loads(result.output)
        self.assertTrue(
            parsed_result['data']['lifecycle-state'] == 'DELETED'
            or parsed_result['data']['lifecycle-state'] == 'DELETING')
def test_run_all_operations(runner, config_file, config_profile, debug):
    """Successfully calls every operation with required arguments only."""
    bucket_name = 'cli_temp_bucket_' + str(random.randint(0, 1000000)) + ('_debug' if debug else '_no_debug')
    object_name = 'a'

    # ns get
    result = invoke(runner, config_file, config_profile, ['ns', 'get'], debug=debug)
    validate_response(result, includes_debug_data=debug)
    assert util.NAMESPACE in result.output

    # bucket create
    result = invoke(runner, config_file, config_profile,
                    ['bucket', 'create', '-ns', util.NAMESPACE, '--compartment-id', util.COMPARTMENT_ID, '--name',
                     bucket_name], debug=debug)
    validate_response(result, includes_debug_data=debug)

    # object put
    result = invoke(runner, config_file, config_profile,
                    ['object', 'put', '-ns', util.NAMESPACE, '-bn', bucket_name, '--name', object_name, '--file',
                     CONTENT_INPUT_FILE, '--encryption-key-file', GENERATED_ENC_KEY1_FILE], debug=debug)
    validate_response(result, includes_debug_data=debug)

    # object get without SSE-C headers should result in a 400
    result = invoke(runner, config_file, config_profile,
                    ['object', 'get', '-ns', util.NAMESPACE, '-bn', bucket_name, '--name', object_name, '--file',
                     CONTENT_OUTPUT_FILE], debug=debug)
    util.validate_service_error(result, 'The service returned error code 400', debug)

    # object get with the wrong SSE-C key should result in a 403
    result = invoke(runner, config_file, config_profile,
                    ['object', 'get', '-ns', util.NAMESPACE, '-bn', bucket_name, '--name', object_name, '--file',
                     CONTENT_OUTPUT_FILE, '--encryption-key-file', GENERATED_ENC_KEY2_FILE], debug=debug)
    util.validate_service_error(result, 'The service returned error code 403', debug)

    # object get with the correct SSE-C key
    result = invoke(runner, config_file, config_profile,
                    ['object', 'get', '-ns', util.NAMESPACE, '-bn', bucket_name, '--name', object_name, '--file',
                     CONTENT_OUTPUT_FILE, '--encryption-key-file', GENERATED_ENC_KEY1_FILE], debug=debug)
    validate_response(result, json_response_expected=False, includes_debug_data=debug)
    assertEqual(get_file_content(CONTENT_INPUT_FILE), get_file_content(CONTENT_OUTPUT_FILE))

    # object head without any SSE-C data should fail with 400
    result = invoke(runner, config_file, config_profile,
                    ['object', 'head', '-ns', util.NAMESPACE, '-bn', bucket_name, '--name', object_name], debug=debug)
    util.validate_service_error(result, 'The service returned error code 400', debug)

    # object head with an incorrect SSE-C key should fail with 403
    result = invoke(runner, config_file, config_profile,
                    ['object', 'head', '-ns', util.NAMESPACE, '-bn', bucket_name, '--name', object_name,
                     '--encryption-key-file', GENERATED_ENC_KEY2_FILE], debug=debug)
    util.validate_service_error(result, 'The service returned error code 403', debug)

    # object head with the right SSE-C key
    result = invoke(runner, config_file, config_profile,
                    ['object', 'head', '-ns', util.NAMESPACE, '-bn', bucket_name, '--name', object_name,
                     '--encryption-key-file', GENERATED_ENC_KEY1_FILE], debug=debug)
    validate_response(result, includes_debug_data=debug)

    # object list (doesn't require SSE-C information)
    result = invoke(runner, config_file, config_profile, ['object', 'list', '-ns', util.NAMESPACE, '-bn', bucket_name],
                    debug=debug)
    validate_response(result, includes_debug_data=debug)

    # object delete (doesn't require SSE-C information)
    result = invoke(runner, config_file, config_profile,
                    ['object', 'delete', '-ns', util.NAMESPACE, '-bn', bucket_name, '--name', object_name], input='n',
                    debug=debug)
    assert result.exit_code != 0
    result = invoke(runner, config_file, config_profile,
                    ['object', 'delete', '-ns', util.NAMESPACE, '-bn', bucket_name, '--name', object_name], input='y',
                    debug=debug)
    validate_response(result, json_response_expected=False, includes_debug_data=debug)

    # bucket delete
    result = invoke(runner, config_file, config_profile,
                    ['bucket', 'delete', '-ns', util.NAMESPACE, '--name', bucket_name, '--force'], debug=debug)
    validate_response(result, includes_debug_data=debug)
def test_run_all_operations(runner, config_file, config_profile, debug):
    """Successfully calls every operation with required arguments only."""
    bucket_name = 'cli_temp_bucket_' + str(random.randint(
        0, 1000000)) + ('_debug' if debug else '_no_debug')
    object_name = 'a'

    # ns get
    result = invoke(runner,
                    config_file,
                    config_profile, ['ns', 'get'],
                    debug=debug)
    validate_response(result, includes_debug_data=debug)
    assert util.NAMESPACE in result.output

    # bucket create
    result = invoke(
        runner,
        config_file,
        config_profile, [
            'bucket', 'create', '-ns', util.NAMESPACE, '--compartment-id',
            util.COMPARTMENT_ID, '--name', bucket_name
        ],
        debug=debug)
    validate_response(result, includes_debug_data=debug)

    # object put
    result = invoke(
        runner,
        config_file,
        config_profile, [
            'object', 'put', '-ns', util.NAMESPACE, '-bn', bucket_name,
            '--name', object_name, '--file', CONTENT_INPUT_FILE,
            '--encryption-key-file', GENERATED_ENC_KEY1_FILE
        ],
        debug=debug)
    validate_response(result, includes_debug_data=debug)

    # object get without SSE-C headers should result in a 400
    result = invoke(
        runner,
        config_file,
        config_profile, [
            'object', 'get', '-ns', util.NAMESPACE, '-bn', bucket_name,
            '--name', object_name, '--file', CONTENT_OUTPUT_FILE
        ],
        debug=debug)
    util.validate_service_error(result, 'The service returned error code 400',
                                debug)

    # object get with the wrong SSE-C key should result in a 403
    result = invoke(
        runner,
        config_file,
        config_profile, [
            'object', 'get', '-ns', util.NAMESPACE, '-bn', bucket_name,
            '--name', object_name, '--file', CONTENT_OUTPUT_FILE,
            '--encryption-key-file', GENERATED_ENC_KEY2_FILE
        ],
        debug=debug)
    util.validate_service_error(result, 'The service returned error code 403',
                                debug)

    # object get with the correct SSE-C key
    result = invoke(
        runner,
        config_file,
        config_profile, [
            'object', 'get', '-ns', util.NAMESPACE, '-bn', bucket_name,
            '--name', object_name, '--file', CONTENT_OUTPUT_FILE,
            '--encryption-key-file', GENERATED_ENC_KEY1_FILE
        ],
        debug=debug)
    validate_response(result,
                      json_response_expected=False,
                      includes_debug_data=debug)
    assertEqual(get_file_content(CONTENT_INPUT_FILE),
                get_file_content(CONTENT_OUTPUT_FILE))

    # object head without any SSE-C data should fail with 400
    result = invoke(runner,
                    config_file,
                    config_profile, [
                        'object', 'head', '-ns', util.NAMESPACE, '-bn',
                        bucket_name, '--name', object_name
                    ],
                    debug=debug)
    util.validate_service_error(result, 'The service returned error code 400',
                                debug)

    # object head with an incorrect SSE-C key should fail with 403
    result = invoke(runner,
                    config_file,
                    config_profile, [
                        'object', 'head', '-ns', util.NAMESPACE, '-bn',
                        bucket_name, '--name', object_name,
                        '--encryption-key-file', GENERATED_ENC_KEY2_FILE
                    ],
                    debug=debug)
    util.validate_service_error(result, 'The service returned error code 403',
                                debug)

    # object head with the right SSE-C key
    result = invoke(runner,
                    config_file,
                    config_profile, [
                        'object', 'head', '-ns', util.NAMESPACE, '-bn',
                        bucket_name, '--name', object_name,
                        '--encryption-key-file', GENERATED_ENC_KEY1_FILE
                    ],
                    debug=debug)
    validate_response(result, includes_debug_data=debug)

    # object reencrypt using the default/Oracle-managed key
    result = invoke(runner,
                    config_file,
                    config_profile, [
                        'object', 'reencrypt', '-ns', util.NAMESPACE, '-bn',
                        bucket_name, '--name', object_name,
                        '--source-encryption-key-file', GENERATED_ENC_KEY1_FILE
                    ],
                    debug=debug)
    validate_response(result, includes_debug_data=debug)

    # reencrypting the object again using the default/Oracle-managed key should not fail (no-op)
    result = invoke(runner,
                    config_file,
                    config_profile, [
                        'object', 'reencrypt', '-ns', util.NAMESPACE, '-bn',
                        bucket_name, '--name', object_name
                    ],
                    debug=debug)
    validate_response(result, includes_debug_data=debug)

    # object head without any SSE-C data should succeed
    result = invoke(runner,
                    config_file,
                    config_profile, [
                        'object', 'head', '-ns', util.NAMESPACE, '-bn',
                        bucket_name, '--name', object_name
                    ],
                    debug=debug)
    validate_response(result, includes_debug_data=debug)

    # reencrypt the object using an SSE-C key
    result = invoke(runner,
                    config_file,
                    config_profile, [
                        'object', 'reencrypt', '-ns', util.NAMESPACE, '-bn',
                        bucket_name, '--name', object_name,
                        '--encryption-key-file', GENERATED_ENC_KEY1_FILE
                    ],
                    debug=debug)
    validate_response(result, includes_debug_data=debug)

    # object head without any SSE-C data should fail
    result = invoke(runner,
                    config_file,
                    config_profile, [
                        'object', 'head', '-ns', util.NAMESPACE, '-bn',
                        bucket_name, '--name', object_name
                    ],
                    debug=debug)
    util.validate_service_error(result, 'The service returned error code 400',
                                debug)

    # object head with the right SSE-C key should succeed
    result = invoke(runner,
                    config_file,
                    config_profile, [
                        'object', 'head', '-ns', util.NAMESPACE, '-bn',
                        bucket_name, '--name', object_name,
                        '--encryption-key-file', GENERATED_ENC_KEY1_FILE
                    ],
                    debug=debug)
    validate_response(result, includes_debug_data=debug)

    # reencrypt the object using yet another SSE-C key
    result = invoke(
        runner,
        config_file,
        config_profile, [
            'object', 'reencrypt', '-ns', util.NAMESPACE, '-bn', bucket_name,
            '--name', object_name, '--source-encryption-key-file',
            GENERATED_ENC_KEY1_FILE, '--encryption-key-file',
            GENERATED_ENC_KEY2_FILE
        ],
        debug=debug)
    validate_response(result, includes_debug_data=debug)

    # object head without any SSE-C data should fail
    result = invoke(runner,
                    config_file,
                    config_profile, [
                        'object', 'head', '-ns', util.NAMESPACE, '-bn',
                        bucket_name, '--name', object_name
                    ],
                    debug=debug)
    util.validate_service_error(result, 'The service returned error code 400',
                                debug)

    # object head with an incorrect SSE-C key should fail with 403
    result = invoke(runner,
                    config_file,
                    config_profile, [
                        'object', 'head', '-ns', util.NAMESPACE, '-bn',
                        bucket_name, '--name', object_name,
                        '--encryption-key-file', GENERATED_ENC_KEY1_FILE
                    ],
                    debug=debug)
    util.validate_service_error(result, 'The service returned error code 403',
                                debug)

    # object head with the right SSE-C key should succeed
    result = invoke(runner,
                    config_file,
                    config_profile, [
                        'object', 'head', '-ns', util.NAMESPACE, '-bn',
                        bucket_name, '--name', object_name,
                        '--encryption-key-file', GENERATED_ENC_KEY2_FILE
                    ],
                    debug=debug)
    validate_response(result, includes_debug_data=debug)

    # specifying both KMS and SSE-C encryption keys to reencrypt the object should result in a 400 error
    result = invoke(
        runner,
        config_file,
        config_profile, [
            'object', 'reencrypt', '-ns', util.NAMESPACE, '-bn', bucket_name,
            '--name', object_name, '--kms-key-id', 'kms123456',
            '--encryption-key-file', GENERATED_ENC_KEY1_FILE
        ],
        debug=debug)
    util.validate_service_error(
        result,
        'The object re-encryption key must be specified either in the kmsKeyId field or in the sseCustomerKey field, but not in both',
        debug)

    # object list (doesn't require SSE-C information)
    result = invoke(
        runner,
        config_file,
        config_profile,
        ['object', 'list', '-ns', util.NAMESPACE, '-bn', bucket_name],
        debug=debug)
    validate_response(result, includes_debug_data=debug)

    # object delete (doesn't require SSE-C information)
    result = invoke(runner,
                    config_file,
                    config_profile, [
                        'object', 'delete', '-ns', util.NAMESPACE, '-bn',
                        bucket_name, '--name', object_name
                    ],
                    input='n',
                    debug=debug)
    assert result.exit_code != 0
    result = invoke(runner,
                    config_file,
                    config_profile, [
                        'object', 'delete', '-ns', util.NAMESPACE, '-bn',
                        bucket_name, '--name', object_name
                    ],
                    input='y',
                    debug=debug)
    validate_response(result,
                      json_response_expected=False,
                      includes_debug_data=debug)

    # bucket delete
    result = invoke(runner,
                    config_file,
                    config_profile, [
                        'bucket', 'delete', '-ns', util.NAMESPACE, '--name',
                        bucket_name, '--force'
                    ],
                    debug=debug)
    validate_response(result, includes_debug_data=debug)
Beispiel #7
0
def test_patch_rrset_records(zone, runner, config_file, config_profile):
    zone_id = zone[0]
    zone_name = zone[1]

    failing_record_operations = [{
        "operation": "REQUIRE",
        "domain": zone_name,
        "isProtected": True,
        "rdata": "127.0.0.1",
        "recordHash": "abc123",
        "rrsetVersion": "1",
        "rtype": "A",
        "ttl": 86400
    }]

    params = [
        'record', 'rrset', 'patch', '--zone-name-or-id', zone_name, '--domain',
        zone_name, '--rtype', 'A', '--items',
        json.dumps(failing_record_operations)
    ]

    result = invoke(runner, config_file, config_profile, params)
    util.validate_service_error(result)

    successful_record_operations = [{
        "operation": "ADD",
        "domain": zone_name,
        "isProtected": True,
        "rdata": "127.0.0.1",
        "recordHash": "abc123",
        "rrsetVersion": "1",
        "rtype": "A",
        "ttl": 86400
    }]

    params = [
        'record', 'rrset', 'patch', '--zone-name-or-id', zone_id, '--domain',
        zone_name, '--rtype', 'A', '--items',
        json.dumps(successful_record_operations)
    ]

    result = invoke(runner, config_file, config_profile, params)
    util.validate_response(result)

    params = [
        'record', 'rrset', 'get', '--zone-name-or-id', zone_id, '--domain',
        zone_name, '--rtype', 'A'
    ]

    result = invoke(runner, config_file, config_profile, params)
    util.validate_response(result)

    records = json.loads(result.output)['data']['items']
    a_record = [record for record in records if record['rtype'] == 'A'][0]

    # remove added TXT record
    remove_record_operation = [{
        "operation": "REMOVE",
        "domain": zone_name,
        "rdata": a_record['rdata'],
        "recordHash": a_record['record-hash'],
        "rtype": a_record['rtype']
    }]

    params = [
        'record', 'rrset', 'patch', '--zone-name-or-id', zone_id, '--domain',
        zone_name, '--rtype', 'A', '--items',
        json.dumps(remove_record_operation)
    ]

    result = invoke(runner, config_file, config_profile, params)
    util.validate_response(result)

    # retrieve zone to determine current version
    params = ['zone', 'get', '--zone-name-or-id', zone_id]

    result = invoke(runner, config_file, config_profile, params)
    util.validate_response(result)

    current_zone_version = json.loads(result.output)['data']['version']

    # fetch zone records list for current version
    params = [
        'record', 'rrset', 'get', '--zone-name-or-id', zone_id, '--domain',
        zone_name, '--rtype', 'A', '--zone-version', current_zone_version
    ]

    result = invoke(runner, config_file, config_profile, params)
    util.validate_response(result)

    # assert that TXT record was removed
    remaining_a_records = [
        record for record in json.loads(result.output)['data']['items']
        if record['rtype'] == 'A'
    ]
    assert len(remaining_a_records) == 0