mirror of
https://github.com/ansible/awx.git
synced 2026-01-12 10:30:03 -03:30
Merge pull request #7629 from ryanpetrello/k8s-creds
add the ability to specify K8S/OCP credentials on a Job Template Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
This commit is contained in:
commit
765595fd11
@ -4100,7 +4100,8 @@ class JobLaunchSerializer(BaseSerializer):
|
||||
errors.setdefault('credentials', []).append(_(
|
||||
'Cannot assign multiple {} credentials.'
|
||||
).format(cred.unique_hash(display=True)))
|
||||
if cred.credential_type.kind not in ('ssh', 'vault', 'cloud', 'net'):
|
||||
if cred.credential_type.kind not in ('ssh', 'vault', 'cloud',
|
||||
'net', 'kubernetes'):
|
||||
errors.setdefault('credentials', []).append(_(
|
||||
'Cannot assign a Credential of kind `{}`'
|
||||
).format(cred.credential_type.kind))
|
||||
|
||||
@ -2657,7 +2657,7 @@ class JobTemplateCredentialsList(SubListCreateAttachDetachAPIView):
|
||||
return {"error": _("Cannot assign multiple {credential_type} credentials.").format(
|
||||
credential_type=sub.unique_hash(display=True))}
|
||||
kind = sub.credential_type.kind
|
||||
if kind not in ('ssh', 'vault', 'cloud', 'net'):
|
||||
if kind not in ('ssh', 'vault', 'cloud', 'net', 'kubernetes'):
|
||||
return {'error': _('Cannot assign a Credential of kind `{}`.').format(kind)}
|
||||
|
||||
return super(JobTemplateCredentialsList, self).is_valid_relation(parent, sub, created)
|
||||
|
||||
@ -101,3 +101,17 @@ def openstack(cred, env, private_data_dir):
|
||||
f.close()
|
||||
os.chmod(path, stat.S_IRUSR | stat.S_IWUSR)
|
||||
env['OS_CLIENT_CONFIG_FILE'] = path
|
||||
|
||||
|
||||
def kubernetes_bearer_token(cred, env, private_data_dir):
|
||||
env['K8S_AUTH_HOST'] = cred.get_input('host', default='')
|
||||
env['K8S_AUTH_API_KEY'] = cred.get_input('bearer_token', default='')
|
||||
if cred.get_input('verify_ssl') and 'ssl_ca_cert' in cred.inputs:
|
||||
env['K8S_AUTH_VERIFY_SSL'] = 'True'
|
||||
handle, path = tempfile.mkstemp(dir=private_data_dir)
|
||||
with os.fdopen(handle, 'w') as f:
|
||||
os.chmod(path, stat.S_IRUSR | stat.S_IWUSR)
|
||||
f.write(cred.get_input('ssl_ca_cert'))
|
||||
env['K8S_AUTH_SSL_CA_CERT'] = path
|
||||
else:
|
||||
env['K8S_AUTH_VERIFY_SSL'] = 'False'
|
||||
|
||||
@ -220,7 +220,7 @@ def test_create_valid_kind(kind, get, post, admin):
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@pytest.mark.parametrize('kind', ['ssh', 'vault', 'scm', 'insights'])
|
||||
@pytest.mark.parametrize('kind', ['ssh', 'vault', 'scm', 'insights', 'kubernetes'])
|
||||
def test_create_invalid_kind(kind, get, post, admin):
|
||||
response = post(reverse('api:credential_type_list'), {
|
||||
'kind': kind,
|
||||
|
||||
@ -483,25 +483,26 @@ def test_job_launch_pass_with_prompted_vault_password(machine_credential, vault_
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_job_launch_JT_with_credentials(machine_credential, credential, net_credential, deploy_jobtemplate):
|
||||
def test_job_launch_JT_with_credentials(machine_credential, credential, net_credential, kube_credential, deploy_jobtemplate):
|
||||
deploy_jobtemplate.ask_credential_on_launch = True
|
||||
deploy_jobtemplate.save()
|
||||
|
||||
kv = dict(credentials=[credential.pk, net_credential.pk, machine_credential.pk])
|
||||
kv = dict(credentials=[credential.pk, net_credential.pk, machine_credential.pk, kube_credential.pk])
|
||||
serializer = JobLaunchSerializer(data=kv, context={'template': deploy_jobtemplate})
|
||||
validated = serializer.is_valid()
|
||||
assert validated, serializer.errors
|
||||
|
||||
kv['credentials'] = [credential, net_credential, machine_credential] # convert to internal value
|
||||
kv['credentials'] = [credential, net_credential, machine_credential, kube_credential] # convert to internal value
|
||||
prompted_fields, ignored_fields, errors = deploy_jobtemplate._accept_or_ignore_job_kwargs(
|
||||
_exclude_errors=['required', 'prompts'], **kv)
|
||||
job_obj = deploy_jobtemplate.create_unified_job(**prompted_fields)
|
||||
|
||||
creds = job_obj.credentials.all()
|
||||
assert len(creds) == 3
|
||||
assert len(creds) == 4
|
||||
assert credential in creds
|
||||
assert net_credential in creds
|
||||
assert machine_credential in creds
|
||||
assert kube_credential in creds
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
|
||||
@ -1037,6 +1037,43 @@ class TestJobCredentials(TestJobExecution):
|
||||
assert '--vault-id dev@prompt' in ' '.join(args)
|
||||
assert '--vault-id prod@prompt' in ' '.join(args)
|
||||
|
||||
@pytest.mark.parametrize("verify", (True, False))
|
||||
def test_k8s_credential(self, job, private_data_dir, verify):
|
||||
k8s = CredentialType.defaults['kubernetes_bearer_token']()
|
||||
inputs = {
|
||||
'host': 'https://example.org/',
|
||||
'bearer_token': 'token123',
|
||||
}
|
||||
if verify:
|
||||
inputs['verify_ssl'] = True
|
||||
inputs['ssl_ca_cert'] = 'CERTDATA'
|
||||
credential = Credential(
|
||||
pk=1,
|
||||
credential_type=k8s,
|
||||
inputs = inputs,
|
||||
)
|
||||
credential.inputs['bearer_token'] = encrypt_field(credential, 'bearer_token')
|
||||
job.credentials.add(credential)
|
||||
|
||||
env = {}
|
||||
safe_env = {}
|
||||
credential.credential_type.inject_credential(
|
||||
credential, env, safe_env, [], private_data_dir
|
||||
)
|
||||
|
||||
assert env['K8S_AUTH_HOST'] == 'https://example.org/'
|
||||
assert env['K8S_AUTH_API_KEY'] == 'token123'
|
||||
|
||||
if verify:
|
||||
assert env['K8S_AUTH_VERIFY_SSL'] == 'True'
|
||||
cert = open(env['K8S_AUTH_SSL_CA_CERT'], 'r').read()
|
||||
assert cert == 'CERTDATA'
|
||||
else:
|
||||
assert env['K8S_AUTH_VERIFY_SSL'] == 'False'
|
||||
assert 'K8S_AUTH_SSL_CA_CERT' not in env
|
||||
|
||||
assert safe_env['K8S_AUTH_API_KEY'] == tasks.HIDDEN_PASSWORD
|
||||
|
||||
def test_aws_cloud_credential(self, job, private_data_dir):
|
||||
aws = CredentialType.defaults['aws']()
|
||||
credential = Credential(
|
||||
|
||||
@ -67,6 +67,10 @@
|
||||
&--external:before {
|
||||
content: '\f14c'
|
||||
}
|
||||
|
||||
&--kubernetes:before, &--kubernetes_bearer_token:before {
|
||||
content: '\f0c2';
|
||||
}
|
||||
}
|
||||
|
||||
.TagComponent-button {
|
||||
|
||||
@ -111,7 +111,7 @@ function multiCredentialModalController(GetBasePath, qs, MultiCredentialService)
|
||||
|
||||
scope.credentialTypes.forEach((credentialType => {
|
||||
if(credentialType.kind
|
||||
.match(/^(machine|cloud|net|ssh|vault)$/)) {
|
||||
.match(/^(machine|cloud|net|ssh|vault|kubernetes)$/)) {
|
||||
scope.displayedCredentialTypes.push(credentialType);
|
||||
}
|
||||
}));
|
||||
|
||||
@ -29,6 +29,7 @@
|
||||
<i class="fa fa-code-fork MultiCredential-tagIcon" ng-switch-when="scm"></i>
|
||||
<i class="fa fa-key MultiCredential-tagIcon" ng-switch-when="ssh"></i>
|
||||
<i class="fa fa-archive MultiCredential-tagIcon" ng-switch-when="vault"></i>
|
||||
<i class="fa fa-cloud MultiCredential-tagIcon" ng-switch-when="kubernetes"></i>
|
||||
</div>
|
||||
<div class="MultiCredential-tag MultiCredential-tag--deletable">
|
||||
<span ng-if="!tag.info" class="MultiCredential-name--label ng-binding">
|
||||
|
||||
@ -26,6 +26,7 @@
|
||||
<i class="fa fa-code-fork MultiCredential-tagIcon" ng-switch-when="scm"></i>
|
||||
<i class="fa fa-key MultiCredential-tagIcon" ng-switch-when="ssh"></i>
|
||||
<i class="fa fa-archive MultiCredential-tagIcon" ng-switch-when="vault"></i>
|
||||
<i class="fa fa-cloud MultiCredential-tagIcon" ng-switch-when="kubernetes"></i>
|
||||
</div>
|
||||
<div class="MultiCredential-iconContainer" ng-switch="tag.kind" ng-if="!fieldIsDisabled">
|
||||
<i class="fa fa-cloud MultiCredential-tagIcon" ng-switch-when="cloud"></i>
|
||||
@ -34,6 +35,7 @@
|
||||
<i class="fa fa-code-fork MultiCredential-tagIcon" ng-switch-when="scm"></i>
|
||||
<i class="fa fa-key MultiCredential-tagIcon" ng-switch-when="ssh"></i>
|
||||
<i class="fa fa-archive MultiCredential-tagIcon" ng-switch-when="vault"></i>
|
||||
<i class="fa fa-cloud MultiCredential-tagIcon" ng-switch-when="kubernetes"></i>
|
||||
</div>
|
||||
<div class="MultiCredential-tag"
|
||||
ng-class="{'MultiCredential-tag--deletable': !fieldIsDisabled, 'MultiCredential-tag--disabled': fieldIsDisabled}">
|
||||
|
||||
@ -55,7 +55,7 @@ export default [ 'ProcessErrors', 'CredentialTypeModel', 'TemplatesStrings', '$f
|
||||
vm.promptDataClone.prompts.credentials.credentialTypeOptions = [];
|
||||
response.data.results.forEach((credentialTypeRow => {
|
||||
vm.promptDataClone.prompts.credentials.credentialTypes[credentialTypeRow.id] = credentialTypeRow.kind;
|
||||
if(credentialTypeRow.kind.match(/^(cloud|net|ssh|vault)$/)) {
|
||||
if(credentialTypeRow.kind.match(/^(cloud|net|ssh|vault|kubernetes)$/)) {
|
||||
if(credentialTypeRow.kind === 'ssh') {
|
||||
vm.promptDataClone.prompts.credentials.credentialKind = credentialTypeRow.id.toString();
|
||||
}
|
||||
|
||||
@ -7,7 +7,7 @@ class CredentialTypes extends Base {
|
||||
}
|
||||
|
||||
async loadAllTypes(
|
||||
acceptableKinds = ['machine', 'cloud', 'net', 'ssh', 'vault']
|
||||
acceptableKinds = ['machine', 'cloud', 'net', 'ssh', 'vault', 'kubernetes']
|
||||
) {
|
||||
const pageSize = 200;
|
||||
// The number of credential types a user can have is unlimited. In practice, it is unlikely for
|
||||
|
||||
23
docs/licenses/ruamel.ordereddict.txt
Normal file
23
docs/licenses/ruamel.ordereddict.txt
Normal file
@ -0,0 +1,23 @@
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2007-2017 Anthon van der Neut/Ruamel BVBA
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
@ -32,8 +32,8 @@ django-oauth-toolkit==1.1.3 # via -r /awx_devel/requirements/requirements.in
|
||||
django-pglocks==1.0.4 # via -r /awx_devel/requirements/requirements.in
|
||||
django-polymorphic==2.1.2 # via -r /awx_devel/requirements/requirements.in
|
||||
django-qsstats-magic==1.1.0 # via -r /awx_devel/requirements/requirements.in
|
||||
django-redis==4.5.0
|
||||
django-radius==1.3.3 # via -r /awx_devel/requirements/requirements.in
|
||||
django-redis==4.5.0 # via -r /awx_devel/requirements/requirements.in
|
||||
django-solo==1.1.3 # via -r /awx_devel/requirements/requirements.in
|
||||
django-split-settings==1.0.0 # via -r /awx_devel/requirements/requirements.in
|
||||
django-taggit==1.2.0 # via -r /awx_devel/requirements/requirements.in
|
||||
@ -100,7 +100,7 @@ python3-openid==3.1.0 # via social-auth-core
|
||||
python3-saml==1.9.0 # via -r /awx_devel/requirements/requirements.in
|
||||
pytz==2019.3 # via django, irc, tempora, twilio
|
||||
pyyaml==5.3.1 # via -r /awx_devel/requirements/requirements.in, ansible-runner, djangorestframework-yaml, kubernetes
|
||||
redis==3.4.1 # via -r /awx_devel/requirements/requirements.in
|
||||
redis==3.4.1 # via -r /awx_devel/requirements/requirements.in, django-redis
|
||||
requests-oauthlib==1.3.0 # via kubernetes, msrest, social-auth-core
|
||||
requests==2.23.0 # via -r /awx_devel/requirements/requirements.in, adal, azure-keyvault, django-oauth-toolkit, kubernetes, msrest, requests-oauthlib, slackclient, social-auth-core, twilio
|
||||
rsa==4.0 # via google-auth
|
||||
|
||||
@ -62,5 +62,7 @@ requests
|
||||
requests-credssp==1.0.2 # For windows authentication awx/issues/1144
|
||||
# OpenStack
|
||||
openstacksdk==0.37.0
|
||||
# Openshift/k8s
|
||||
openshift>=0.11.0 # minimum version to pull in new pyyaml for CVE-2017-18342
|
||||
pip==19.3.1 # see upgrade blockers
|
||||
setuptools==41.6.0 # see upgrade blockers
|
||||
setuptools==41.6.0 # see upgrade blockers
|
||||
|
||||
@ -26,7 +26,7 @@ azure-mgmt-loganalytics==0.2.0 # via -r /awx_devel/requirements/requirements_an
|
||||
azure-mgmt-marketplaceordering==0.1.0 # via -r /awx_devel/requirements/requirements_ansible.in
|
||||
azure-mgmt-monitor==0.5.2 # via -r /awx_devel/requirements/requirements_ansible.in
|
||||
azure-mgmt-network==2.3.0 # via -r /awx_devel/requirements/requirements_ansible.in
|
||||
azure-mgmt-nspkg==2.0.0 # via -r /awx_devel/requirements/requirements_ansible.in, azure-mgmt-authorization, azure-mgmt-automation, azure-mgmt-batch, azure-mgmt-cdn, azure-mgmt-compute, azure-mgmt-containerinstance, azure-mgmt-containerregistry, azure-mgmt-containerservice, azure-mgmt-cosmosdb, azure-mgmt-devtestlabs, azure-mgmt-dns, azure-mgmt-hdinsight, azure-mgmt-iothub, azure-mgmt-keyvault, azure-mgmt-loganalytics, azure-mgmt-marketplaceordering, azure-mgmt-monitor, azure-mgmt-network, azure-mgmt-rdbms, azure-mgmt-redis, azure-mgmt-resource, azure-mgmt-servicebus, azure-mgmt-sql, azure-mgmt-storage, azure-mgmt-trafficmanager, azure-mgmt-web
|
||||
azure-mgmt-nspkg==2.0.0; python_version < "3" # via -r /awx_devel/requirements/requirements_ansible.in, azure-mgmt-authorization, azure-mgmt-automation, azure-mgmt-batch, azure-mgmt-cdn, azure-mgmt-compute, azure-mgmt-containerinstance, azure-mgmt-containerregistry, azure-mgmt-containerservice, azure-mgmt-cosmosdb, azure-mgmt-devtestlabs, azure-mgmt-dns, azure-mgmt-hdinsight, azure-mgmt-iothub, azure-mgmt-keyvault, azure-mgmt-loganalytics, azure-mgmt-marketplaceordering, azure-mgmt-monitor, azure-mgmt-network, azure-mgmt-rdbms, azure-mgmt-redis, azure-mgmt-resource, azure-mgmt-servicebus, azure-mgmt-sql, azure-mgmt-storage, azure-mgmt-trafficmanager, azure-mgmt-web
|
||||
azure-mgmt-rdbms==1.4.1 # via -r /awx_devel/requirements/requirements_ansible.in
|
||||
azure-mgmt-redis==5.0.0 # via -r /awx_devel/requirements/requirements_ansible.in
|
||||
azure-mgmt-resource==2.1.0 # via -r /awx_devel/requirements/requirements_ansible.in
|
||||
@ -43,7 +43,7 @@ boto3==1.9.223 # via -r /awx_devel/requirements/requirements_ansible.
|
||||
boto==2.47.0 # via -r /awx_devel/requirements/requirements_ansible.in
|
||||
botocore==1.12.253 # via boto3, s3transfer
|
||||
cachetools==3.1.1 # via google-auth
|
||||
certifi==2019.11.28 # via msrest, requests
|
||||
certifi==2019.11.28 # via kubernetes, msrest, requests
|
||||
cffi==1.13.2 # via bcrypt, cryptography, pynacl
|
||||
chardet==3.0.4 # via requests
|
||||
colorama==0.4.3 # via azure-cli-core, knack
|
||||
@ -53,18 +53,19 @@ docutils==0.15.2 # via botocore
|
||||
dogpile.cache==0.9.0 # via openstacksdk
|
||||
enum34==1.1.6; python_version < "3" # via cryptography, knack, msrest, ovirt-engine-sdk-python
|
||||
futures==3.3.0; python_version < "3" # via openstacksdk, s3transfer
|
||||
google-auth==1.6.2 # via -r /awx_devel/requirements/requirements_ansible.in
|
||||
google-auth==1.6.2 # via -r /awx_devel/requirements/requirements_ansible.in, kubernetes
|
||||
humanfriendly==4.18 # via azure-cli-core
|
||||
idna==2.8 # via requests
|
||||
ipaddress==1.0.23; python_version < "3" # via cryptography, openstacksdk
|
||||
ipaddress==1.0.23; python_version < "3" # via cryptography, kubernetes, openstacksdk
|
||||
iso8601==0.1.12 # via keystoneauth1, openstacksdk
|
||||
isodate==0.6.0 # via msrest
|
||||
jinja2==2.10.1 # via -r /awx_devel/requirements/requirements_ansible.in
|
||||
jinja2==2.10.1 # via -r /awx_devel/requirements/requirements_ansible.in, openshift
|
||||
jmespath==0.9.4 # via azure-cli-core, boto3, botocore, knack, openstacksdk
|
||||
jsonpatch==1.24 # via openstacksdk
|
||||
jsonpointer==2.0 # via jsonpatch
|
||||
keystoneauth1==3.18.0 # via openstacksdk
|
||||
knack==0.3.3 # via azure-cli-core
|
||||
kubernetes==11.0.0 # via openshift
|
||||
lxml==4.4.2 # via ncclient
|
||||
markupsafe==1.1.1 # via jinja2
|
||||
monotonic==1.5; python_version < "3" # via humanfriendly
|
||||
@ -76,6 +77,7 @@ netaddr==0.7.19 # via -r /awx_devel/requirements/requirements_ansible.
|
||||
netifaces==0.10.9 # via openstacksdk
|
||||
ntlm-auth==1.4.0 # via requests-credssp, requests-ntlm
|
||||
oauthlib==3.1.0 # via requests-oauthlib
|
||||
openshift==0.11.2 # via -r /awx_devel/requirements/requirements_ansible.in
|
||||
openstacksdk==0.37.0 # via -r /awx_devel/requirements/requirements_ansible.in
|
||||
os-service-types==1.7.0 # via keystoneauth1, openstacksdk
|
||||
ovirt-engine-sdk-python==4.3.0 # via -r /awx_devel/requirements/requirements_ansible.in
|
||||
@ -93,27 +95,32 @@ pykerberos==1.2.1 # via requests-kerberos
|
||||
pynacl==1.3.0 # via paramiko
|
||||
pyopenssl==19.1.0 # via azure-cli-core, requests-credssp
|
||||
pyparsing==2.4.5 # via packaging
|
||||
python-dateutil==2.8.1 # via adal, azure-storage, botocore
|
||||
python-dateutil==2.8.1 # via adal, azure-storage, botocore, kubernetes
|
||||
python-string-utils==0.6.0; python_version < "3" # via openshift
|
||||
pyvmomi==6.7.3 # via -r /awx_devel/requirements/requirements_ansible.in
|
||||
pywinrm[kerberos]==0.3.0 # via -r /awx_devel/requirements/requirements_ansible.in
|
||||
pyyaml==5.2 # via azure-cli-core, knack, openstacksdk
|
||||
pyyaml==5.2 # via azure-cli-core, knack, kubernetes, openstacksdk
|
||||
requests-credssp==1.0.2 # via -r /awx_devel/requirements/requirements_ansible.in
|
||||
requests-kerberos==0.12.0 # via pywinrm
|
||||
requests-ntlm==1.1.0 # via pywinrm
|
||||
requests-oauthlib==1.3.0 # via msrest
|
||||
requests==2.22.0 # via -r /awx_devel/requirements/requirements_ansible.in, adal, apache-libcloud, azure-cli-core, azure-keyvault, azure-storage, keystoneauth1, msrest, pyvmomi, pywinrm, requests-credssp, requests-kerberos, requests-ntlm, requests-oauthlib
|
||||
requests-oauthlib==1.3.0 # via kubernetes, msrest
|
||||
requests==2.22.0 # via -r /awx_devel/requirements/requirements_ansible.in, adal, apache-libcloud, azure-cli-core, azure-keyvault, azure-storage, keystoneauth1, kubernetes, msrest, pyvmomi, pywinrm, requests-credssp, requests-kerberos, requests-ntlm, requests-oauthlib
|
||||
requestsexceptions==1.4.0 # via openstacksdk
|
||||
rsa==4.0 # via google-auth
|
||||
ruamel.ordereddict==0.4.14; python_version < "3" # via ruamel.yaml
|
||||
ruamel.yaml.clib==0.2.0 # via ruamel.yaml
|
||||
ruamel.yaml==0.16.10 # via openshift
|
||||
s3transfer==0.2.1 # via boto3
|
||||
selectors2==2.0.1 # via ncclient
|
||||
six==1.13.0 # via azure-cli-core, bcrypt, cryptography, google-auth, isodate, keystoneauth1, knack, munch, ncclient, openstacksdk, ovirt-engine-sdk-python, packaging, pynacl, pyopenssl, python-dateutil, pyvmomi, pywinrm, requests-credssp, stevedore
|
||||
six==1.13.0 # via azure-cli-core, bcrypt, cryptography, google-auth, isodate, keystoneauth1, knack, kubernetes, munch, ncclient, openshift, openstacksdk, ovirt-engine-sdk-python, packaging, pynacl, pyopenssl, python-dateutil, pyvmomi, pywinrm, requests-credssp, stevedore, websocket-client
|
||||
stevedore==1.31.0 # via keystoneauth1
|
||||
tabulate==0.8.2 # via azure-cli-core, knack
|
||||
typing==3.7.4.1; python_version < "3" # via msrest
|
||||
urllib3==1.25.7 # via botocore, requests
|
||||
urllib3==1.25.7 # via botocore, kubernetes, requests
|
||||
websocket-client==0.57.0 # via kubernetes
|
||||
wheel==0.33.6 # via azure-cli-core (overriden, see upgrade blockers)
|
||||
xmltodict==0.12.0 # via pywinrm
|
||||
|
||||
# The following packages are considered to be unsafe in a requirements file:
|
||||
pip==19.3.1 # via -r /awx_devel/requirements/requirements_ansible.in, azure-cli-core
|
||||
setuptools==41.6.0 # via -r /awx_devel/requirements/requirements_ansible.in, ncclient
|
||||
setuptools==41.6.0 # via -r /awx_devel/requirements/requirements_ansible.in, kubernetes, ncclient
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user