~andrewjbeach/juju-ci-tools/make-local-patcher

1401.1.1 by Christopher Lee
Initial WIP adding tests for autoload-credentials command.
1
#!/usr/bin/env python
2
"""Tests for the autoload-credentials command."""
3
4
from __future__ import print_function
5
6
import argparse
1401.3.5 by Christopher Lee
Generate uniq. credentials in a predictable manner.
7
from collections import (
8
    defaultdict,
9
    namedtuple,
10
    )
11
import itertools
1401.1.24 by Christopher Lee
Add GCE tests for credentials.
12
import json
1401.1.1 by Christopher Lee
Initial WIP adding tests for autoload-credentials command.
13
import logging
1401.1.7 by Christopher Lee
Addition of testing for aws env-var and file based search
14
import os
1401.1.1 by Christopher Lee
Initial WIP adding tests for autoload-credentials command.
15
import sys
1401.1.8 by Christopher Lee
Added envvar openstack tests. Clean up some implementation details.
16
import tempfile
1401.3.3 by Christopher Lee
Correct order of imports
17
from textwrap import dedent
18
19
import pexpect
1401.2.3 by Christopher Lee
Simplify writing aws config file
20
1401.1.17 by Christopher Lee
Fix imports
21
from jujupy import (
22
    EnvJujuClient,
23
    JujuData,
24
    )
1401.1.2 by Christopher Lee
Update test as per review. Use more existing functionality.
25
from utility import (
26
    configure_logging,
27
    enforce_juju_path,
1401.3.3 by Christopher Lee
Correct order of imports
28
    ensure_dir,
1401.1.2 by Christopher Lee
Update test as per review. Use more existing functionality.
29
    temp_dir,
1401.1.17 by Christopher Lee
Fix imports
30
    )
1401.1.1 by Christopher Lee
Initial WIP adding tests for autoload-credentials command.
31
32
33
__metaclass__ = type
34
35
36
log = logging.getLogger("assess_autoload_credentials")
37
38
1401.1.14 by Christopher Lee
Refactor use of pexpect.expect answers to not be mised in w/ envvar deatils.
39
# Store details for querying the interactive command.
40
# cloud_listing: String response for choosing credential to save
41
# save_name: String response in which to save the credential under.
42
ExpectAnswers = namedtuple('ExpectAnswers', ['cloud_listing', 'save_name'])
43
1401.1.8 by Christopher Lee
Added envvar openstack tests. Clean up some implementation details.
44
# Store details for setting up a clouds credentials as well as what to compare
45
# during test.
46
# env_var_changes: dict
47
# expected_details: dict
1401.1.14 by Christopher Lee
Refactor use of pexpect.expect answers to not be mised in w/ envvar deatils.
48
# expect_answers: ExpectAnswers object
1401.1.8 by Christopher Lee
Added envvar openstack tests. Clean up some implementation details.
49
CloudDetails = namedtuple(
50
    'CloudDetails',
1401.1.14 by Christopher Lee
Refactor use of pexpect.expect answers to not be mised in w/ envvar deatils.
51
    ['env_var_changes', 'expected_details', 'expect_answers']
1401.3.2 by Christopher Lee
Further indent fixes.
52
    )
1401.1.8 by Christopher Lee
Added envvar openstack tests. Clean up some implementation details.
53
54
1401.3.5 by Christopher Lee
Generate uniq. credentials in a predictable manner.
55
class CredentialIdCounter:
56
    _counter = defaultdict(itertools.count)
57
58
    @classmethod
59
    def id(cls, provider_name):
60
        return cls._counter[provider_name].next()
1401.1.8 by Christopher Lee
Added envvar openstack tests. Clean up some implementation details.
61
62
1401.1.1 by Christopher Lee
Initial WIP adding tests for autoload-credentials command.
63
def assess_autoload_credentials(juju_bin):
1401.1.7 by Christopher Lee
Addition of testing for aws env-var and file based search
64
    test_scenarios = [
65
        ('AWS using environment variables', aws_envvar_test_details),
66
        ('AWS using credentials file', aws_directory_test_details),
1401.1.22 by Christopher Lee
Fix typo
67
        ('OS using environment variables', openstack_envvar_test_details),
1401.1.23 by Christopher Lee
Add test for openstack using credentials file
68
        ('OS using credentials file', openstack_directory_test_details),
1401.1.24 by Christopher Lee
Add GCE tests for credentials.
69
        ('GCE using envvar with credentials file',
70
         gce_envvar_with_file_test_details),
71
        ('GCE using credentials file',
72
         gce_file_test_details),
1401.1.18 by Christopher Lee
Adding USER to env_var_changes to a saner place.
73
        ]
1401.1.1 by Christopher Lee
Initial WIP adding tests for autoload-credentials command.
74
1401.1.7 by Christopher Lee
Addition of testing for aws env-var and file based search
75
    for scenario_name, scenario_setup in test_scenarios:
76
        log.info('* Starting test scenario: {}'.format(scenario_name))
1401.2.8 by Christopher Lee
Rename test method as per projects naming convention.
77
        ensure_autoload_credentials_stores_details(juju_bin, scenario_setup)
78
1401.1.8 by Christopher Lee
Added envvar openstack tests. Clean up some implementation details.
79
    for scenario_name, scenario_setup in test_scenarios:
80
        log.info(
1401.1.9 by Christopher Lee
Merge pre-req. branch changes.
81
            '* Starting [overwrite] test, scenario: {}'.format(scenario_name))
82
        ensure_autoload_credentials_overwrite_existing(
83
            juju_bin, scenario_setup)
84
1401.2.8 by Christopher Lee
Rename test method as per projects naming convention.
85
86
def ensure_autoload_credentials_stores_details(juju_bin, cloud_details_fn):
1401.1.6 by Christopher Lee
Modify to move towards testing different cloud credential types with the same test (e.g. aws, openstack)
87
    """Test covering loading and storing credentials using autoload-credentials
88
89
    :param juju_bin: The full path to the juju binary to use for the test run.
1401.1.11 by Christopher Lee
Fix typo and import order
90
    :param cloud_details_fn: A callable that takes the 3 arguments `user`
1401.1.8 by Christopher Lee
Added envvar openstack tests. Clean up some implementation details.
91
      string, `tmp_dir` path string and client EnvJujuClient and will returns a
92
      `CloudDetails` object used to setup creation of credential details &
93
      comparison of the result.
94
95
    """
96
    user = 'testing_user'
97
    with temp_dir() as tmp_dir:
1401.2.9 by Christopher Lee
Use separate temp directories for juju_home and general scratch
98
        tmp_juju_home = tempfile.mkdtemp(dir=tmp_dir)
99
        tmp_scratch_dir = tempfile.mkdtemp(dir=tmp_dir)
1401.1.8 by Christopher Lee
Added envvar openstack tests. Clean up some implementation details.
100
        client = EnvJujuClient.by_version(
1401.1.21 by Christopher Lee
Fix import and dangling parens.
101
            JujuData('local', juju_home=tmp_juju_home), juju_bin, False)
1401.1.8 by Christopher Lee
Added envvar openstack tests. Clean up some implementation details.
102
1401.1.9 by Christopher Lee
Merge pre-req. branch changes.
103
        cloud_details = cloud_details_fn(user, tmp_scratch_dir, client)
1401.1.8 by Christopher Lee
Added envvar openstack tests. Clean up some implementation details.
104
1401.1.14 by Christopher Lee
Refactor use of pexpect.expect answers to not be mised in w/ envvar deatils.
105
        run_autoload_credentials(
106
            client,
107
            cloud_details.env_var_changes,
108
            cloud_details.expect_answers)
1401.1.8 by Christopher Lee
Added envvar openstack tests. Clean up some implementation details.
109
110
        client.env.load_yaml()
111
112
        assert_credentials_contains_expected_results(
113
            client.env.credentials,
1401.1.21 by Christopher Lee
Fix import and dangling parens.
114
            cloud_details.expected_details)
1401.1.8 by Christopher Lee
Added envvar openstack tests. Clean up some implementation details.
115
116
1401.1.9 by Christopher Lee
Merge pre-req. branch changes.
117
def ensure_autoload_credentials_overwrite_existing(juju_bin, cloud_details_fn):
1401.1.8 by Christopher Lee
Added envvar openstack tests. Clean up some implementation details.
118
    """Storing credentials using autoload-credentials must overwrite existing.
119
120
    :param juju_bin: The full path to the juju binary to use for the test run.
1401.1.11 by Christopher Lee
Fix typo and import order
121
    :param cloud_details_fn: A callable that takes the 3 arguments `user`
1401.1.8 by Christopher Lee
Added envvar openstack tests. Clean up some implementation details.
122
      string, `tmp_dir` path string and client EnvJujuClient and will returns a
123
      `CloudDetails` object used to setup creation of credential details &
124
      comparison of the result.
125
126
    """
127
    user = 'testing_user'
128
    with temp_dir() as tmp_dir:
1401.1.10 by Christopher Lee
Update overwrite test to use separate tmp dirs.
129
        tmp_juju_home = tempfile.mkdtemp(dir=tmp_dir)
130
        tmp_scratch_dir = tempfile.mkdtemp(dir=tmp_dir)
1401.1.8 by Christopher Lee
Added envvar openstack tests. Clean up some implementation details.
131
        client = EnvJujuClient.by_version(
1401.1.12 by Christopher Lee
Ensure overwrite is happening and cleanup paren indent.
132
            JujuData('local', juju_home=tmp_juju_home), juju_bin, False)
1401.1.8 by Christopher Lee
Added envvar openstack tests. Clean up some implementation details.
133
1401.1.12 by Christopher Lee
Ensure overwrite is happening and cleanup paren indent.
134
        initial_details = cloud_details_fn(
135
            user, tmp_scratch_dir, client)
1401.1.8 by Christopher Lee
Added envvar openstack tests. Clean up some implementation details.
136
1401.1.15 by Christopher Lee
Merge pre-req. branch fixes.
137
        run_autoload_credentials(
138
            client,
139
            initial_details.env_var_changes,
140
            initial_details.expect_answers)
1401.1.8 by Christopher Lee
Added envvar openstack tests. Clean up some implementation details.
141
142
        # Now run again with a second lot of details.
1401.1.12 by Christopher Lee
Ensure overwrite is happening and cleanup paren indent.
143
        overwrite_details = cloud_details_fn(user, tmp_scratch_dir, client)
144
145
        if (
146
                overwrite_details.expected_details ==
147
                initial_details.expected_details):
148
            raise ValueError(
149
                'Attempting to use identical values for overwriting')
150
1401.1.15 by Christopher Lee
Merge pre-req. branch fixes.
151
        run_autoload_credentials(
152
            client,
153
            overwrite_details.env_var_changes,
154
            overwrite_details.expect_answers)
1401.1.8 by Christopher Lee
Added envvar openstack tests. Clean up some implementation details.
155
156
        client.env.load_yaml()
157
158
        assert_credentials_contains_expected_results(
159
            client.env.credentials,
1401.1.12 by Christopher Lee
Ensure overwrite is happening and cleanup paren indent.
160
            overwrite_details.expected_details)
1401.1.2 by Christopher Lee
Update test as per review. Use more existing functionality.
161
162
1401.2.1 by Christopher Lee
Clean up paren indentation
163
def assert_credentials_contains_expected_results(credentials, expected):
164
    if credentials != expected:
1401.1.5 by Christopher Lee
Be strict when checking resulting credential details.
165
        raise ValueError(
166
            'Actual credentials do not match expected credentials.\n'
167
            'Expected: {expected}\nGot: {got}\n'.format(
1401.2.1 by Christopher Lee
Clean up paren indentation
168
                expected=expected,
1401.2.11 by Christopher Lee
Fix indentation to match project expectations.
169
                got=credentials))
1401.1.2 by Christopher Lee
Update test as per review. Use more existing functionality.
170
171
1401.1.14 by Christopher Lee
Refactor use of pexpect.expect answers to not be mised in w/ envvar deatils.
172
def run_autoload_credentials(client, envvars, answers):
1401.1.1 by Christopher Lee
Initial WIP adding tests for autoload-credentials command.
173
    """Execute the command 'juju autoload-credentials'.
174
175
    Simple interaction, calls juju autoload-credentials selects the first
176
    option and then quits.
177
1401.1.4 by Christopher Lee
Add JujuEnvClient.expect with test. Update assess test to use new functionality.
178
    :param client: EnvJujuClient from which juju will be called.
1401.1.2 by Christopher Lee
Update test as per review. Use more existing functionality.
179
    :param envvars: Dictionary containing environment variables to be used
180
      during execution.
1401.3.1 by Christopher Lee
Fix docstring re: answers.
181
    :param answers: ExpectAnswers object containing answers for the interactive
182
      command
1401.1.1 by Christopher Lee
Initial WIP adding tests for autoload-credentials command.
183
184
    """
1401.1.4 by Christopher Lee
Add JujuEnvClient.expect with test. Update assess test to use new functionality.
185
    process = client.expect(
1401.2.1 by Christopher Lee
Clean up paren indentation
186
        'autoload-credentials', extra_env=envvars, include_e=False)
1401.1.14 by Christopher Lee
Refactor use of pexpect.expect answers to not be mised in w/ envvar deatils.
187
    process.expect('.*1. {} \(.*\).*'.format(answers.cloud_listing))
1401.1.1 by Christopher Lee
Initial WIP adding tests for autoload-credentials command.
188
    process.sendline('1')
189
1401.1.2 by Christopher Lee
Update test as per review. Use more existing functionality.
190
    process.expect(
1401.2.1 by Christopher Lee
Clean up paren indentation
191
        'Enter cloud to which the credential belongs, or Q to quit.*')
1401.1.14 by Christopher Lee
Refactor use of pexpect.expect answers to not be mised in w/ envvar deatils.
192
    process.sendline(answers.save_name)
1401.1.2 by Christopher Lee
Update test as per review. Use more existing functionality.
193
    process.expect(
1401.1.14 by Christopher Lee
Refactor use of pexpect.expect answers to not be mised in w/ envvar deatils.
194
        'Saved {listing_display} to cloud {save_name}'.format(
195
            listing_display=answers.cloud_listing,
196
            save_name=answers.save_name))
1401.1.2 by Christopher Lee
Update test as per review. Use more existing functionality.
197
    process.sendline('q')
1401.1.1 by Christopher Lee
Initial WIP adding tests for autoload-credentials command.
198
    process.expect(pexpect.EOF)
199
200
    if process.isalive():
1401.2.5 by Christopher Lee
Ensure process is terminated if needed.
201
        log.debug('juju process is still running: {}'.format(str(process)))
202
        process.terminate(force=True)
1401.1.1 by Christopher Lee
Initial WIP adding tests for autoload-credentials command.
203
        raise AssertionError('juju process failed to terminate')
204
205
1401.1.8 by Christopher Lee
Added envvar openstack tests. Clean up some implementation details.
206
def aws_envvar_test_details(user, tmp_dir, client, credential_details=None):
207
    """client is un-used for AWS"""
208
    credential_details = credential_details or aws_credential_dict_generator()
209
    access_key = credential_details['access_key']
210
    secret_key = credential_details['secret_key']
1401.1.6 by Christopher Lee
Modify to move towards testing different cloud credential types with the same test (e.g. aws, openstack)
211
    env_var_changes = get_aws_environment(user, access_key, secret_key)
1401.1.1 by Christopher Lee
Initial WIP adding tests for autoload-credentials command.
212
1401.1.14 by Christopher Lee
Refactor use of pexpect.expect answers to not be mised in w/ envvar deatils.
213
    answers = ExpectAnswers(
214
        cloud_listing='aws credential "{}"'.format(user),
215
        save_name='aws')
216
1401.1.7 by Christopher Lee
Addition of testing for aws env-var and file based search
217
    expected_details = get_aws_expected_details_dict(
1401.2.1 by Christopher Lee
Clean up paren indentation
218
        user, access_key, secret_key)
1401.1.7 by Christopher Lee
Addition of testing for aws env-var and file based search
219
1401.1.14 by Christopher Lee
Refactor use of pexpect.expect answers to not be mised in w/ envvar deatils.
220
    return CloudDetails(env_var_changes, expected_details, answers)
1401.1.8 by Christopher Lee
Added envvar openstack tests. Clean up some implementation details.
221
222
223
def aws_directory_test_details(user, tmp_dir, client, credential_details=None):
224
    """client is un-used for AWS"""
225
    credential_details = credential_details or aws_credential_dict_generator()
226
    access_key = credential_details['access_key']
227
    secret_key = credential_details['secret_key']
1401.1.7 by Christopher Lee
Addition of testing for aws env-var and file based search
228
    expected_details = get_aws_expected_details_dict(
1401.2.1 by Christopher Lee
Clean up paren indentation
229
        'default', access_key, secret_key)
1401.1.7 by Christopher Lee
Addition of testing for aws env-var and file based search
230
231
    write_aws_config_file(tmp_dir, access_key, secret_key)
232
1401.1.14 by Christopher Lee
Refactor use of pexpect.expect answers to not be mised in w/ envvar deatils.
233
    answers = ExpectAnswers(
234
        cloud_listing='aws credential "{}"'.format('default'),
235
        save_name='aws')
236
237
    env_var_changes = dict(HOME=tmp_dir)
238
239
    return CloudDetails(env_var_changes, expected_details, answers)
1401.1.7 by Christopher Lee
Addition of testing for aws env-var and file based search
240
241
242
def get_aws_expected_details_dict(cloud_name, access_key, secret_key):
1401.1.5 by Christopher Lee
Be strict when checking resulting credential details.
243
    # Build credentials yaml file-like datastructure.
1401.1.7 by Christopher Lee
Addition of testing for aws env-var and file based search
244
    return {
1401.1.5 by Christopher Lee
Be strict when checking resulting credential details.
245
        'credentials': {
246
            'aws': {
1401.1.7 by Christopher Lee
Addition of testing for aws env-var and file based search
247
                cloud_name: {
1401.1.5 by Christopher Lee
Be strict when checking resulting credential details.
248
                    'auth-type': 'access-key',
249
                    'access-key': access_key,
250
                    'secret-key': secret_key,
1401.2.11 by Christopher Lee
Fix indentation to match project expectations.
251
                    }
1401.1.5 by Christopher Lee
Be strict when checking resulting credential details.
252
                }
253
            }
254
        }
1401.1.1 by Christopher Lee
Initial WIP adding tests for autoload-credentials command.
255
1401.1.2 by Christopher Lee
Update test as per review. Use more existing functionality.
256
1401.1.6 by Christopher Lee
Modify to move towards testing different cloud credential types with the same test (e.g. aws, openstack)
257
def get_aws_environment(user, access_key, secret_key):
1401.1.14 by Christopher Lee
Refactor use of pexpect.expect answers to not be mised in w/ envvar deatils.
258
    """Return a dictionary containing keys suitable for AWS env vars."""
1401.1.6 by Christopher Lee
Modify to move towards testing different cloud credential types with the same test (e.g. aws, openstack)
259
    return dict(
1401.1.18 by Christopher Lee
Adding USER to env_var_changes to a saner place.
260
        USER=user,
1401.1.6 by Christopher Lee
Modify to move towards testing different cloud credential types with the same test (e.g. aws, openstack)
261
        AWS_ACCESS_KEY_ID=access_key,
1401.2.11 by Christopher Lee
Fix indentation to match project expectations.
262
        AWS_SECRET_ACCESS_KEY=secret_key)
1401.1.1 by Christopher Lee
Initial WIP adding tests for autoload-credentials command.
263
264
1401.1.7 by Christopher Lee
Addition of testing for aws env-var and file based search
265
def write_aws_config_file(tmp_dir, access_key, secret_key):
266
    """Write aws credentials file to tmp_dir
267
268
    :return: String path of created credentials file.
269
270
    """
271
    config_dir = os.path.join(tmp_dir, '.aws')
272
    config_file = os.path.join(config_dir, 'credentials')
273
    ensure_dir(config_dir)
274
1401.2.3 by Christopher Lee
Simplify writing aws config file
275
    config_contents = dedent("""\
276
    [default]
277
    aws_access_key_id={}
278
    aws_secret_access_key={}
279
    """.format(access_key, secret_key))
280
1401.1.7 by Christopher Lee
Addition of testing for aws env-var and file based search
281
    with open(config_file, 'w') as f:
1401.2.3 by Christopher Lee
Simplify writing aws config file
282
        f.write(config_contents)
1401.1.7 by Christopher Lee
Addition of testing for aws env-var and file based search
283
284
    return config_file
285
286
1401.1.8 by Christopher Lee
Added envvar openstack tests. Clean up some implementation details.
287
def aws_credential_dict_generator():
1401.3.5 by Christopher Lee
Generate uniq. credentials in a predictable manner.
288
    call_id = CredentialIdCounter.id('aws')
289
    creds = 'aws-credentials-{}'.format(call_id)
1401.1.8 by Christopher Lee
Added envvar openstack tests. Clean up some implementation details.
290
    return dict(
1401.3.5 by Christopher Lee
Generate uniq. credentials in a predictable manner.
291
        access_key=creds,
292
        secret_key=creds)
1401.1.8 by Christopher Lee
Added envvar openstack tests. Clean up some implementation details.
293
294
295
def openstack_envvar_test_details(
1401.3.2 by Christopher Lee
Further indent fixes.
296
        user, tmp_dir, client, credential_details=None):
1401.1.8 by Christopher Lee
Added envvar openstack tests. Clean up some implementation details.
297
    if credential_details is None:
298
        credential_details = openstack_credential_dict_generator()
299
1401.1.23 by Christopher Lee
Add test for openstack using credentials file
300
    expected_details, answers = setup_basic_openstack_test_details(
301
        client, user, credential_details)
302
303
    env_var_changes = get_openstack_envvar_changes(user, credential_details)
304
305
    return CloudDetails(env_var_changes, expected_details, answers)
306
307
308
def get_openstack_envvar_changes(user, credential_details):
309
    return dict(
310
        USER=user,
311
        OS_USERNAME=user,
312
        OS_PASSWORD=credential_details['os_password'],
313
        OS_TENANT_NAME=credential_details['os_tenant_name'])
314
315
316
def openstack_directory_test_details(
317
        user, tmp_dir, client, credential_details=None
318
):
319
    if credential_details is None:
320
        credential_details = openstack_credential_dict_generator()
321
322
    expected_details, answers = setup_basic_openstack_test_details(
323
        client, user, credential_details)
324
325
    write_openstack_config_file(tmp_dir, user, credential_details)
326
    env_var_changes = dict(HOME=tmp_dir)
327
328
    return CloudDetails(env_var_changes, expected_details, answers)
329
330
331
def setup_basic_openstack_test_details(client, user, credential_details):
1401.1.8 by Christopher Lee
Added envvar openstack tests. Clean up some implementation details.
332
    ensure_openstack_personal_cloud_exists(client)
333
    expected_details = get_openstack_expected_details_dict(
1401.1.21 by Christopher Lee
Fix import and dangling parens.
334
        user, credential_details)
1401.1.14 by Christopher Lee
Refactor use of pexpect.expect answers to not be mised in w/ envvar deatils.
335
    answers = ExpectAnswers(
336
        cloud_listing='openstack region ".*" project "{}" user "{}"'.format(
337
            credential_details['os_tenant_name'],
338
            user),
339
        save_name='testing_openstack')
1401.1.23 by Christopher Lee
Add test for openstack using credentials file
340
341
    return expected_details, answers
342
343
344
def write_openstack_config_file(tmp_dir, user, credential_details):
345
    credentials_file = os.path.join(tmp_dir, '.novarc')
346
    with open(credentials_file, 'w') as f:
347
        credentials = dedent("""\
1401.1.29 by Christopher Lee
Correct novarc file to include 'exports'
348
        export OS_USERNAME={user}
349
        export OS_PASSWORD={password}
350
        export OS_TENANT_NAME={tenant_name}
1401.1.23 by Christopher Lee
Add test for openstack using credentials file
351
        """.format(
352
            user=user,
353
            password=credential_details['os_password'],
354
            tenant_name=credential_details['os_tenant_name'],
355
            ))
356
        f.write(credentials)
357
    return credentials_file
1401.1.8 by Christopher Lee
Added envvar openstack tests. Clean up some implementation details.
358
359
360
def ensure_openstack_personal_cloud_exists(client):
1401.1.13 by Christopher Lee
Simplify storing new clouds.yaml file.
361
    os_cloud = {
1401.3.4 by Christopher Lee
Add default 'clouds' to load_yaml(). No need to check for existing clouds.
362
        'testing_openstack': {
363
            'type': 'openstack',
364
            'regions': {
365
                'test1': {
366
                    'endpoint': 'https://example.com',
367
                    'auth-types': ['access-key', 'userpass']
368
                    }
1401.1.21 by Christopher Lee
Fix import and dangling parens.
369
                }
1401.1.8 by Christopher Lee
Added envvar openstack tests. Clean up some implementation details.
370
            }
371
        }
1401.3.4 by Christopher Lee
Add default 'clouds' to load_yaml(). No need to check for existing clouds.
372
    client.env.clouds['clouds'] = os_cloud
373
    client.env.dump_yaml(client.env.juju_home, config=None)
1401.1.13 by Christopher Lee
Simplify storing new clouds.yaml file.
374
375
1401.1.8 by Christopher Lee
Added envvar openstack tests. Clean up some implementation details.
376
def get_openstack_expected_details_dict(user, credential_details):
377
    return {
378
        'credentials': {
379
            'testing_openstack': {
380
                user: {
381
                    'auth-type': 'userpass',
382
                    'domain-name': '',
383
                    'password': credential_details['os_password'],
384
                    'tenant-name': credential_details['os_tenant_name'],
385
                    'username': user
1401.1.21 by Christopher Lee
Fix import and dangling parens.
386
                    }
1401.1.8 by Christopher Lee
Added envvar openstack tests. Clean up some implementation details.
387
                }
388
            }
389
        }
390
391
392
def openstack_credential_dict_generator():
1401.3.5 by Christopher Lee
Generate uniq. credentials in a predictable manner.
393
    call_id = CredentialIdCounter.id('openstack')
394
    creds = 'openstack-credentials-{}'.format(call_id)
1401.1.8 by Christopher Lee
Added envvar openstack tests. Clean up some implementation details.
395
    return dict(
1401.3.5 by Christopher Lee
Generate uniq. credentials in a predictable manner.
396
        os_tenant_name=creds,
397
        os_password=creds)
1401.1.8 by Christopher Lee
Added envvar openstack tests. Clean up some implementation details.
398
399
1401.1.24 by Christopher Lee
Add GCE tests for credentials.
400
def gce_envvar_with_file_test_details(
401
        user, tmp_dir, client, credential_details=None
402
):
403
    if credential_details is None:
404
        credential_details = gce_credential_dict_generator()
405
    credentials_path = write_gce_config_file(tmp_dir, credential_details)
406
407
    answers = ExpectAnswers(
408
        cloud_listing='google credential "{}"'.format(
409
            credential_details['client_email']),
410
        save_name='google')
411
412
    expected_details = get_gce_expected_details_dict(user, credentials_path)
413
414
    env_var_changes = dict(
415
        USER=user,
416
        GOOGLE_APPLICATION_CREDENTIALS=credentials_path,
417
        )
418
419
    return CloudDetails(env_var_changes, expected_details, answers)
420
421
422
def gce_file_test_details(
423
        user, tmp_dir, client, credential_details=None
424
):
425
    if credential_details is None:
426
        credential_details = gce_credential_dict_generator()
427
428
    home_path, credentials_path = write_gce_home_config_file(
429
        tmp_dir, credential_details)
430
431
    answers = ExpectAnswers(
432
        cloud_listing='google credential "{}"'.format(
433
            credential_details['client_email']),
434
        save_name='google')
435
436
    expected_details = get_gce_expected_details_dict(user, credentials_path)
437
438
    env_var_changes = dict(USER=user, HOME=home_path)
439
440
    return CloudDetails(env_var_changes, expected_details, answers)
441
442
443
def write_gce_config_file(tmp_dir, credential_details, filename=None):
444
445
    details = dict(
446
        type='service_account',
447
        client_id=credential_details['client_id'],
448
        client_email=credential_details['client_email'],
449
        private_key=credential_details['private_key'])
450
451
    # Generate a unique filename if none provided as this is stored and used in
452
    # comparisons.
1401.1.28 by Christopher Lee
Update GCE tests to use new id/creds generators.
453
    filename = filename or 'gce-file-config-{}.json'.format(
454
        CredentialIdCounter.id('gce-fileconfig'))
1401.1.24 by Christopher Lee
Add GCE tests for credentials.
455
    credential_file = os.path.join(tmp_dir, filename)
456
    with open(credential_file, 'w') as f:
457
        json.dump(details, f)
458
459
    return credential_file
460
461
462
def write_gce_home_config_file(tmp_dir, credential_details):
463
    """Returns a tuple contining a new HOME path and credential file path."""
464
    # Add a unique string for home dir so each file path is unique within the
465
    # stored credentials file.
1401.1.28 by Christopher Lee
Update GCE tests to use new id/creds generators.
466
    home_dir = os.path.join(tmp_dir, 'gce-homedir-{}'.format(
467
        CredentialIdCounter.id('gce-homedir')))
1401.1.24 by Christopher Lee
Add GCE tests for credentials.
468
    credential_path = os.path.join(home_dir, '.config', 'gcloud')
469
    os.makedirs(credential_path)
470
471
    written_credentials_path = write_gce_config_file(
472
        credential_path,
473
        credential_details,
474
        'application_default_credentials.json')
475
476
    return home_dir, written_credentials_path
477
478
479
def get_gce_expected_details_dict(user, credentials_path):
480
    return {
481
        'credentials': {
482
            'google': {
483
                user: {
484
                    'auth-type': 'jsonfile',
485
                    'file': credentials_path,
486
                    }
487
                }
488
            }
489
        }
490
491
492
def gce_credential_dict_generator():
1401.1.28 by Christopher Lee
Update GCE tests to use new id/creds generators.
493
    call_id = CredentialIdCounter.id('gce')
494
    creds = 'gce-credentials-{}'.format(call_id)
1410.2.2 by Christopher Lee
Fix for unit and assess test. Need valid email address in credentials.
495
    return dict(
496
        client_id=creds,
497
        client_email='{}@example.com'.format(creds),
498
        private_key=creds,
499
        )
1401.1.24 by Christopher Lee
Add GCE tests for credentials.
500
501
1401.1.1 by Christopher Lee
Initial WIP adding tests for autoload-credentials command.
502
def parse_args(argv):
1401.2.10 by Christopher Lee
Fix issues with unit tests.
503
    parser = argparse.ArgumentParser(
504
        description="Test autoload-credentials command.")
1401.1.1 by Christopher Lee
Initial WIP adding tests for autoload-credentials command.
505
    parser.add_argument(
506
        'juju_bin', action=enforce_juju_path,
507
        help='Full path to the Juju binary.')
508
    parser.add_argument(
509
        '--verbose', action='store_const',
510
        default=logging.INFO, const=logging.DEBUG,
511
        help='Verbose test harness output.')
512
513
    return parser.parse_args(argv)
514
515
516
def main(argv=None):
517
    args = parse_args(argv)
518
    configure_logging(args.verbose)
1401.1.2 by Christopher Lee
Update test as per review. Use more existing functionality.
519
1401.1.1 by Christopher Lee
Initial WIP adding tests for autoload-credentials command.
520
    assess_autoload_credentials(args.juju_bin)
521
    return 0
522
523
524
if __name__ == '__main__':
525
    sys.exit(main())