1
0
mirror of https://github.com/ansible/awx.git synced 2024-11-02 01:21:21 +03:00

Merge pull request #425 from ryanpetrello/release_3.2.0

remove support for azure classic
This commit is contained in:
Ryan Petrello 2017-09-18 11:26:55 -04:00 committed by GitHub
commit 21e3078853
19 changed files with 63 additions and 475 deletions

View File

@ -89,7 +89,7 @@ class Metadata(metadata.SimpleMetadata):
# Special handling of inventory source_region choices that vary based on
# selected inventory source.
if field.field_name == 'source_regions':
for cp in ('azure', 'ec2', 'gce'):
for cp in ('azure_rm', 'ec2', 'gce'):
get_regions = getattr(InventorySource, 'get_%s_region_choices' % cp)
field_info['%s_region_choices' % cp] = get_regions()

View File

@ -5,7 +5,7 @@ import re
from django.utils.translation import ugettext_lazy as _
CLOUD_PROVIDERS = ('azure', 'azure_rm', 'ec2', 'gce', 'rax', 'vmware', 'openstack', 'satellite6', 'cloudforms')
CLOUD_PROVIDERS = ('azure_rm', 'ec2', 'gce', 'vmware', 'openstack', 'satellite6', 'cloudforms')
SCHEDULEABLE_PROVIDERS = CLOUD_PROVIDERS + ('custom', 'scm',)
PRIVILEGE_ESCALATION_METHODS = [ ('sudo', _('Sudo')), ('su', _('Su')), ('pbrun', _('Pbrun')), ('pfexec', _('Pfexec')), ('dzdo', _('DZDO')), ('pmrun', _('Pmrun')), ('runas', _('Runas'))]
ANSI_SGR_PATTERN = re.compile(r'\x1b\[[0-9;]*m')

View File

@ -194,7 +194,6 @@ def load_inventory_source(source, group_filter_re=None,
'''
# Sanity check: We sanitize these module names for our API but Ansible proper doesn't follow
# good naming conventions
source = source.replace('azure.py', 'windows_azure.py')
source = source.replace('satellite6.py', 'foreman.py')
source = source.replace('vmware.py', 'vmware_inventory.py')
if not os.path.exists(source):

View File

@ -145,12 +145,12 @@ class Migration(migrations.Migration):
migrations.AlterField(
model_name='inventorysource',
name='source',
field=models.CharField(default=b'', max_length=32, blank=True, choices=[(b'', 'Manual'), (b'file', 'File, Directory or Script'), (b'scm', 'Sourced from a Project'), (b'ec2', 'Amazon EC2'), (b'gce', 'Google Compute Engine'), (b'azure', 'Microsoft Azure Classic (deprecated)'), (b'azure_rm', 'Microsoft Azure Resource Manager'), (b'vmware', 'VMware vCenter'), (b'satellite6', 'Red Hat Satellite 6'), (b'cloudforms', 'Red Hat CloudForms'), (b'openstack', 'OpenStack'), (b'custom', 'Custom Script')]),
field=models.CharField(default=b'', max_length=32, blank=True, choices=[(b'', 'Manual'), (b'file', 'File, Directory or Script'), (b'scm', 'Sourced from a Project'), (b'ec2', 'Amazon EC2'), (b'gce', 'Google Compute Engine'), (b'azure_rm', 'Microsoft Azure Resource Manager'), (b'vmware', 'VMware vCenter'), (b'satellite6', 'Red Hat Satellite 6'), (b'cloudforms', 'Red Hat CloudForms'), (b'openstack', 'OpenStack'), (b'custom', 'Custom Script')]),
),
migrations.AlterField(
model_name='inventoryupdate',
name='source',
field=models.CharField(default=b'', max_length=32, blank=True, choices=[(b'', 'Manual'), (b'file', 'File, Directory or Script'), (b'scm', 'Sourced from a Project'), (b'ec2', 'Amazon EC2'), (b'gce', 'Google Compute Engine'), (b'azure', 'Microsoft Azure Classic (deprecated)'), (b'azure_rm', 'Microsoft Azure Resource Manager'), (b'vmware', 'VMware vCenter'), (b'satellite6', 'Red Hat Satellite 6'), (b'cloudforms', 'Red Hat CloudForms'), (b'openstack', 'OpenStack'), (b'custom', 'Custom Script')]),
field=models.CharField(default=b'', max_length=32, blank=True, choices=[(b'', 'Manual'), (b'file', 'File, Directory or Script'), (b'scm', 'Sourced from a Project'), (b'ec2', 'Amazon EC2'), (b'gce', 'Google Compute Engine'), (b'azure_rm', 'Microsoft Azure Resource Manager'), (b'vmware', 'VMware vCenter'), (b'satellite6', 'Red Hat Satellite 6'), (b'cloudforms', 'Red Hat CloudForms'), (b'openstack', 'OpenStack'), (b'custom', 'Custom Script')]),
),
migrations.AlterField(
model_name='inventorysource',

View File

@ -11,6 +11,7 @@ from awx.main.migrations import _migration_utils as migration_utils
from awx.main.migrations import _reencrypt as reencrypt
from awx.main.migrations import _scan_jobs as scan_jobs
from awx.main.migrations import _credentialtypes as credentialtypes
from awx.main.migrations import _azure_credentials as azurecreds
import awx.main.fields
@ -24,6 +25,8 @@ class Migration(migrations.Migration):
# Inventory Refresh
migrations.RunPython(migration_utils.set_current_apps_for_migrations),
migrations.RunPython(invsrc.remove_rax_inventory_sources),
migrations.RunPython(azurecreds.remove_azure_credentials),
migrations.RunPython(invsrc.remove_azure_inventory_sources),
migrations.RunPython(invsrc.remove_inventory_source_with_no_inventory_link),
migrations.RunPython(invsrc.rename_inventory_sources),
migrations.RunPython(reencrypt.replace_aesecb_fernet),

View File

@ -0,0 +1,15 @@
import logging
from django.db.models import Q
logger = logging.getLogger('awx.main.migrations')
def remove_azure_credentials(apps, schema_editor):
'''Azure is not supported as of 3.2 and greater. Instead, azure_rm is
supported.
'''
Credential = apps.get_model('main', 'Credential')
logger.debug("Removing all Azure Credentials from database.")
Credential.objects.filter(kind='azure').delete()

View File

@ -51,3 +51,12 @@ def remove_inventory_source_with_no_inventory_link(apps, schema_editor):
InventorySource = apps.get_model('main', 'InventorySource')
logger.debug("Removing all InventorySource that have no link to an Inventory from database.")
InventorySource.objects.filter(Q(inventory__organization=None) & Q(deprecated_group__inventory=None)).delete()
def remove_azure_inventory_sources(apps, schema_editor):
'''Azure inventory sources are not supported since 3.2, remove them.
'''
InventorySource = apps.get_model('main', 'InventorySource')
logger.debug("Removing all Azure InventorySource from database.")
InventorySource.objects.filter(source='azure').delete()

View File

@ -52,7 +52,7 @@ PROJECT_UPDATE_JOB_TYPE_CHOICES = [
(PERM_INVENTORY_CHECK, _('Check')),
]
CLOUD_INVENTORY_SOURCES = ['ec2', 'rax', 'vmware', 'gce', 'azure', 'azure_rm', 'openstack', 'custom', 'satellite6', 'cloudforms', 'scm',]
CLOUD_INVENTORY_SOURCES = ['ec2', 'vmware', 'gce', 'azure_rm', 'openstack', 'custom', 'satellite6', 'cloudforms', 'scm',]
VERBOSITY_CHOICES = [
(0, '0 (Normal)'),

View File

@ -57,7 +57,6 @@ class V1Credential(object):
('satellite6', 'Red Hat Satellite 6'),
('cloudforms', 'Red Hat CloudForms'),
('gce', 'Google Compute Engine'),
('azure', 'Microsoft Azure Classic (deprecated)'),
('azure_rm', 'Microsoft Azure Resource Manager'),
('openstack', 'OpenStack'),
('insights', 'Insights'),
@ -934,35 +933,6 @@ def gce(cls):
)
@CredentialType.default
def azure(cls):
return cls(
kind='cloud',
name='Microsoft Azure Classic (deprecated)',
managed_by_tower=True,
inputs={
'fields': [{
'id': 'username',
'label': 'Subscription ID',
'type': 'string',
'help_text': ('Subscription ID is an Azure construct, which is '
'mapped to a username.')
}, {
'id': 'ssh_key_data',
'label': 'Management Certificate',
'type': 'string',
'format': 'ssh_private_key',
'secret': True,
'multiline': True,
'help_text': ('Paste the contents of the PEM file that corresponds '
'to the certificate you uploaded in the Microsoft '
'Azure console.')
}],
'required': ['username', 'ssh_key_data'],
}
)
@CredentialType.default
def azure_rm(cls):
return cls(

View File

@ -867,7 +867,6 @@ class InventorySourceOptions(BaseModel):
('scm', _('Sourced from a Project')),
('ec2', _('Amazon EC2')),
('gce', _('Google Compute Engine')),
('azure', _('Microsoft Azure Classic (deprecated)')),
('azure_rm', _('Microsoft Azure Resource Manager')),
('vmware', _('VMware vCenter')),
('satellite6', _('Red Hat Satellite 6')),
@ -1087,7 +1086,7 @@ class InventorySourceOptions(BaseModel):
return regions
@classmethod
def get_azure_region_choices(self):
def get_azure_rm_region_choices(self):
"""Return a complete list of regions in Microsoft Azure, as a list of
two-tuples.
"""
@ -1095,14 +1094,10 @@ class InventorySourceOptions(BaseModel):
# authenticating first (someone reading these might think there's
# a pattern here!). Therefore, you guessed it, use a list from
# settings.
regions = list(getattr(settings, 'AZURE_REGION_CHOICES', []))
regions = list(getattr(settings, 'AZURE_RM_REGION_CHOICES', []))
regions.insert(0, ('all', 'All'))
return regions
@classmethod
def get_azure_rm_region_choices(self):
return InventorySourceOptions.get_azure_region_choices()
@classmethod
def get_vmware_region_choices(self):
"""Return a complete list of regions in VMware, as a list of two-tuples

View File

@ -1060,9 +1060,6 @@ class RunJob(BaseTask):
env['GCE_EMAIL'] = cloud_cred.username
env['GCE_PROJECT'] = cloud_cred.project
env['GCE_PEM_FILE_PATH'] = cred_files.get(cloud_cred, '')
elif cloud_cred and cloud_cred.kind == 'azure':
env['AZURE_SUBSCRIPTION_ID'] = cloud_cred.username
env['AZURE_CERT_PATH'] = cred_files.get(cloud_cred, '')
elif cloud_cred and cloud_cred.kind == 'azure_rm':
if len(cloud_cred.client) and len(cloud_cred.tenant):
env['AZURE_CLIENT_ID'] = cloud_cred.client
@ -1633,8 +1630,8 @@ class RunInventoryUpdate(BaseTask):
If no private data is needed, return None.
"""
private_data = {'credentials': {}}
# If this is Microsoft Azure or GCE, return the RSA key
if inventory_update.source in ('azure', 'gce'):
# If this is GCE, return the RSA key
if inventory_update.source == 'gce':
credential = inventory_update.credential
private_data['credentials'][credential] = decrypt_field(credential, 'ssh_key_data')
return private_data
@ -1864,9 +1861,6 @@ class RunInventoryUpdate(BaseTask):
env['EC2_INI_PATH'] = cloud_credential
elif inventory_update.source == 'vmware':
env['VMWARE_INI_PATH'] = cloud_credential
elif inventory_update.source == 'azure':
env['AZURE_SUBSCRIPTION_ID'] = passwords.get('source_username', '')
env['AZURE_CERT_PATH'] = cloud_credential
elif inventory_update.source == 'azure_rm':
if len(passwords.get('source_client', '')) and \
len(passwords.get('source_tenant', '')):

View File

@ -1071,43 +1071,6 @@ def test_gce_create_ok(post, organization, admin, version, params):
assert decrypt_field(cred, 'ssh_key_data') == EXAMPLE_PRIVATE_KEY
#
# Azure Classic
#
@pytest.mark.django_db
@pytest.mark.parametrize('version, params', [
['v1', {
'kind': 'azure',
'name': 'Best credential ever',
'username': 'some_username',
'ssh_key_data': EXAMPLE_PRIVATE_KEY
}],
['v2', {
'credential_type': 1,
'name': 'Best credential ever',
'inputs': {
'username': 'some_username',
'ssh_key_data': EXAMPLE_PRIVATE_KEY
}
}]
])
def test_azure_create_ok(post, organization, admin, version, params):
azure = CredentialType.defaults['azure']()
azure.save()
params['organization'] = organization.id
response = post(
reverse('api:credential_list', kwargs={'version': version}),
params,
admin
)
assert response.status_code == 201
assert Credential.objects.count() == 1
cred = Credential.objects.all()[:1].get()
assert cred.inputs['username'] == 'some_username'
assert decrypt_field(cred, 'ssh_key_data') == EXAMPLE_PRIVATE_KEY
#
# Azure Resource Manager
#

View File

@ -19,7 +19,6 @@ EXAMPLE_ENCRYPTED_PRIVATE_KEY = '-----BEGIN PRIVATE KEY-----\nProc-Type: 4,ENCRY
def test_default_cred_types():
assert sorted(CredentialType.defaults.keys()) == [
'aws',
'azure',
'azure_rm',
'cloudforms',
'gce',

View File

@ -269,22 +269,6 @@ def test_gce_migration():
assert Credential.objects.count() == 1
@pytest.mark.django_db
def test_azure_classic_migration():
cred = Credential(name='My Credential')
with migrate(cred, 'azure'):
cred.__dict__.update({
'username': 'bob',
'ssh_key_data': EXAMPLE_PRIVATE_KEY
})
assert cred.credential_type.name == 'Microsoft Azure Classic (deprecated)'
assert cred.inputs['username'] == 'bob'
assert cred.inputs['ssh_key_data'].startswith('$encrypted$')
assert decrypt_field(cred, 'ssh_key_data') == EXAMPLE_PRIVATE_KEY
assert Credential.objects.count() == 1
@pytest.mark.django_db
def test_azure_rm_migration():
cred = Credential(name='My Credential')

View File

@ -35,3 +35,13 @@ def test_inv_src_rename(inventory_source_factory):
inv_src01.refresh_from_db()
# inv-is-t1 is generated in the inventory_source_factory
assert inv_src01.name == 't1 - inv-is-t1 - 0'
@pytest.mark.django_db
def test_azure_inv_src_removal(inventory_source):
inventory_source.source = 'azure'
inventory_source.save()
assert InventorySource.objects.filter(pk=inventory_source.pk).exists()
invsrc.remove_azure_inventory_sources(apps, None)
assert not InventorySource.objects.filter(pk=inventory_source.pk).exists()

View File

@ -544,29 +544,6 @@ class TestJobCredentials(TestJobExecution):
self.run_pexpect.side_effect = run_pexpect_side_effect
self.task.run(self.pk)
def test_azure_credentials(self):
azure = CredentialType.defaults['azure']()
credential = Credential(
pk=1,
credential_type=azure,
inputs = {
'username': 'bob',
'ssh_key_data': self.EXAMPLE_PRIVATE_KEY
}
)
credential.inputs['ssh_key_data'] = encrypt_field(credential, 'ssh_key_data')
self.instance.extra_credentials.add(credential)
def run_pexpect_side_effect(*args, **kwargs):
args, cwd, env, stdout = args
assert env['AZURE_SUBSCRIPTION_ID'] == 'bob'
ssh_key_data = env['AZURE_CERT_PATH']
assert open(ssh_key_data, 'rb').read() == self.EXAMPLE_PRIVATE_KEY
return ['successful', 0]
self.run_pexpect.side_effect = run_pexpect_side_effect
self.task.run(self.pk)
def test_azure_rm_with_tenant(self):
azure = CredentialType.defaults['azure_rm']()
credential = Credential(
@ -1038,29 +1015,25 @@ class TestJobCredentials(TestJobExecution):
gce_credential.inputs['ssh_key_data'] = encrypt_field(gce_credential, 'ssh_key_data')
self.instance.extra_credentials.add(gce_credential)
azure = CredentialType.defaults['azure']()
azure_credential = Credential(
azure_rm = CredentialType.defaults['azure_rm']()
azure_rm_credential = Credential(
pk=2,
credential_type=azure,
credential_type=azure_rm,
inputs = {
'username': 'joe',
'ssh_key_data': 'AZURE: %s' % self.EXAMPLE_PRIVATE_KEY
'subscription': 'some-subscription',
'username': 'bob',
'password': 'secret'
}
)
azure_credential.inputs['ssh_key_data'] = encrypt_field(azure_credential, 'ssh_key_data')
self.instance.extra_credentials.add(azure_credential)
azure_rm_credential.inputs['secret'] = encrypt_field(azure_rm_credential, 'secret')
self.instance.extra_credentials.add(azure_rm_credential)
def run_pexpect_side_effect(*args, **kwargs):
args, cwd, env, stdout = args
assert env['GCE_EMAIL'] == 'bob'
assert env['GCE_PROJECT'] == 'some-project'
ssh_key_data = env['GCE_PEM_FILE_PATH']
assert open(ssh_key_data, 'rb').read() == 'GCE: %s' % self.EXAMPLE_PRIVATE_KEY
assert env['AZURE_SUBSCRIPTION_ID'] == 'joe'
ssh_key_data = env['AZURE_CERT_PATH']
assert open(ssh_key_data, 'rb').read() == 'AZURE: %s' % self.EXAMPLE_PRIVATE_KEY
assert env['AZURE_SUBSCRIPTION_ID'] == 'some-subscription'
assert env['AZURE_AD_USER'] == 'bob'
assert env['AZURE_PASSWORD'] == 'secret'
return ['successful', 0]
@ -1278,31 +1251,6 @@ class TestInventoryUpdateCredentials(TestJobExecution):
self.run_pexpect.side_effect = run_pexpect_side_effect
self.task.run(self.pk)
def test_azure_source(self):
azure = CredentialType.defaults['azure']()
self.instance.source = 'azure'
self.instance.credential = Credential(
pk=1,
credential_type=azure,
inputs = {
'username': 'bob',
'ssh_key_data': self.EXAMPLE_PRIVATE_KEY
}
)
self.instance.credential.inputs['ssh_key_data'] = encrypt_field(
self.instance.credential, 'ssh_key_data'
)
def run_pexpect_side_effect(*args, **kwargs):
args, cwd, env, stdout = args
assert env['AZURE_SUBSCRIPTION_ID'] == 'bob'
ssh_key_data = env['AZURE_CERT_PATH']
assert open(ssh_key_data, 'rb').read() == self.EXAMPLE_PRIVATE_KEY
return ['successful', 0]
self.run_pexpect.side_effect = run_pexpect_side_effect
self.task.run(self.pk)
def test_gce_source(self):
gce = CredentialType.defaults['gce']()
self.instance.source = 'gce'

View File

@ -1,284 +0,0 @@
#!/usr/bin/env python
'''
Windows Azure external inventory script
=======================================
Generates inventory that Ansible can understand by making API request to
Windows Azure using the azure python library.
NOTE: This script assumes Ansible is being executed where azure is already
installed.
pip install azure
Adapted from the ansible Linode plugin by Dan Slimmon.
'''
# (c) 2013, John Whitbeck
#
# This file is part of Ansible,
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
######################################################################
# Standard imports
import re
import sys
import argparse
import os
from urlparse import urlparse
from time import time
try:
import json
except ImportError:
import simplejson as json
try:
from azure.servicemanagement import ServiceManagementService
except ImportError as e:
sys.exit("ImportError: {0}".format(str(e)))
# Imports for ansible
import ConfigParser
class AzureInventory(object):
def __init__(self):
"""Main execution path."""
# Inventory grouped by display group
self.inventory = {}
# Index of deployment name -> host
self.index = {}
self.host_metadata = {}
# Cache setting defaults.
# These can be overridden in settings (see `read_settings`).
cache_dir = os.path.expanduser('~')
self.cache_path_cache = os.path.join(cache_dir, '.ansible-azure.cache')
self.cache_path_index = os.path.join(cache_dir, '.ansible-azure.index')
self.cache_max_age = 0
# Read settings and parse CLI arguments
self.read_settings()
self.read_environment()
self.parse_cli_args()
# Initialize Azure ServiceManagementService
self.sms = ServiceManagementService(self.subscription_id, self.cert_path)
# Cache
if self.args.refresh_cache:
self.do_api_calls_update_cache()
elif not self.is_cache_valid():
self.do_api_calls_update_cache()
if self.args.list_images:
data_to_print = self.json_format_dict(self.get_images(), True)
elif self.args.list or self.args.host:
# Display list of nodes for inventory
if len(self.inventory) == 0:
data = json.loads(self.get_inventory_from_cache())
else:
data = self.inventory
if self.args.host:
data_to_print = self.get_host(self.args.host)
else:
# Add the `['_meta']['hostvars']` information.
hostvars = {}
if len(data) > 0:
for host in set([h for hosts in data.values() for h in hosts if h]):
hostvars[host] = self.get_host(host, jsonify=False)
data['_meta'] = {'hostvars': hostvars}
# JSONify the data.
data_to_print = self.json_format_dict(data, pretty=True)
print(data_to_print)
def get_host(self, hostname, jsonify=True):
"""Return information about the given hostname, based on what
the Windows Azure API provides.
"""
if hostname not in self.host_metadata:
return "No host found: %s" % json.dumps(self.host_metadata)
if jsonify:
return json.dumps(self.host_metadata[hostname])
return self.host_metadata[hostname]
def get_images(self):
images = []
for image in self.sms.list_os_images():
if str(image.label).lower().find(self.args.list_images.lower()) >= 0:
images.append(vars(image))
return json.loads(json.dumps(images, default=lambda o: o.__dict__))
def is_cache_valid(self):
"""Determines if the cache file has expired, or if it is still valid."""
if os.path.isfile(self.cache_path_cache):
mod_time = os.path.getmtime(self.cache_path_cache)
current_time = time()
if (mod_time + self.cache_max_age) > current_time:
if os.path.isfile(self.cache_path_index):
return True
return False
def read_settings(self):
"""Reads the settings from the .ini file."""
config = ConfigParser.SafeConfigParser()
config.read(os.path.dirname(os.path.realpath(__file__)) + '/windows_azure.ini')
# Credentials related
if config.has_option('azure', 'subscription_id'):
self.subscription_id = config.get('azure', 'subscription_id')
if config.has_option('azure', 'cert_path'):
self.cert_path = config.get('azure', 'cert_path')
# Cache related
if config.has_option('azure', 'cache_path'):
cache_path = os.path.expandvars(os.path.expanduser(config.get('azure', 'cache_path')))
self.cache_path_cache = os.path.join(cache_path, 'ansible-azure.cache')
self.cache_path_index = os.path.join(cache_path, 'ansible-azure.index')
if config.has_option('azure', 'cache_max_age'):
self.cache_max_age = config.getint('azure', 'cache_max_age')
def read_environment(self):
''' Reads the settings from environment variables '''
# Credentials
if os.getenv("AZURE_SUBSCRIPTION_ID"):
self.subscription_id = os.getenv("AZURE_SUBSCRIPTION_ID")
if os.getenv("AZURE_CERT_PATH"):
self.cert_path = os.getenv("AZURE_CERT_PATH")
def parse_cli_args(self):
"""Command line argument processing"""
parser = argparse.ArgumentParser(
description='Produce an Ansible Inventory file based on Azure',
)
parser.add_argument('--list', action='store_true', default=True,
help='List nodes (default: True)')
parser.add_argument('--list-images', action='store',
help='Get all available images.')
parser.add_argument('--refresh-cache',
action='store_true', default=False,
help='Force refresh of thecache by making API requests to Azure '
'(default: False - use cache files)',
)
parser.add_argument('--host', action='store',
help='Get all information about an instance.')
self.args = parser.parse_args()
def do_api_calls_update_cache(self):
"""Do API calls, and save data in cache files."""
self.add_cloud_services()
self.write_to_cache(self.inventory, self.cache_path_cache)
self.write_to_cache(self.index, self.cache_path_index)
def add_cloud_services(self):
"""Makes an Azure API call to get the list of cloud services."""
try:
for cloud_service in self.sms.list_hosted_services():
self.add_deployments(cloud_service)
except Exception as e:
sys.exit("Error: Failed to access cloud services - {0}".format(str(e)))
def add_deployments(self, cloud_service):
"""Makes an Azure API call to get the list of virtual machines
associated with a cloud service.
"""
try:
for deployment in self.sms.get_hosted_service_properties(cloud_service.service_name,embed_detail=True).deployments.deployments:
self.add_deployment(cloud_service, deployment)
except Exception as e:
sys.exit("Error: Failed to access deployments - {0}".format(str(e)))
def add_deployment(self, cloud_service, deployment):
"""Adds a deployment to the inventory and index"""
for role in deployment.role_instance_list.role_instances:
try:
# Default port 22 unless port found with name 'SSH'
port = '22'
for ie in role.instance_endpoints.instance_endpoints:
if ie.name == 'SSH':
port = ie.public_port
break
except AttributeError as e:
pass
finally:
self.add_instance(role.instance_name, deployment, port, cloud_service, role.instance_status)
def add_instance(self, hostname, deployment, ssh_port, cloud_service, status):
"""Adds an instance to the inventory and index"""
dest = urlparse(deployment.url).hostname
# Add to index
self.index[hostname] = deployment.name
self.host_metadata[hostname] = dict(ansible_ssh_host=dest,
ansible_ssh_port=int(ssh_port),
instance_status=status,
private_id=deployment.private_id)
# List of all azure deployments
self.push(self.inventory, "azure", hostname)
# Inventory: Group by service name
self.push(self.inventory, self.to_safe(cloud_service.service_name), hostname)
if int(ssh_port) == 22:
self.push(self.inventory, "Cloud_services", hostname)
# Inventory: Group by region
self.push(self.inventory, self.to_safe(cloud_service.hosted_service_properties.location), hostname)
def push(self, my_dict, key, element):
"""Pushed an element onto an array that may not have been defined in the dict."""
if key in my_dict:
my_dict[key].append(element)
else:
my_dict[key] = [element]
def get_inventory_from_cache(self):
"""Reads the inventory from the cache file and returns it as a JSON object."""
cache = open(self.cache_path_cache, 'r')
json_inventory = cache.read()
return json_inventory
def load_index_from_cache(self):
"""Reads the index from the cache file and sets self.index."""
cache = open(self.cache_path_index, 'r')
json_index = cache.read()
self.index = json.loads(json_index)
def write_to_cache(self, data, filename):
"""Writes data in JSON format to a file."""
json_data = self.json_format_dict(data, True)
cache = open(filename, 'w')
cache.write(json_data)
cache.close()
def to_safe(self, word):
"""Escapes any characters that would be invalid in an ansible group name."""
return re.sub("[^A-Za-z0-9\-]", "_", word)
def json_format_dict(self, data, pretty=False):
"""Converts a dict to a JSON object and dumps it as a formatted string."""
if pretty:
return json.dumps(data, sort_keys=True, indent=2)
else:
return json.dumps(data)
AzureInventory()

View File

@ -776,14 +776,12 @@ GCE_HOST_FILTER = r'^.+$'
GCE_EXCLUDE_EMPTY_GROUPS = True
GCE_INSTANCE_ID_VAR = None
# -------------------
# -- Microsoft Azure --
# -------------------
# --------------------------------------
# -- Microsoft Azure Resource Manager --
# --------------------------------------
# It's not possible to get zones in Azure without authenticating, so we
# provide a list here.
AZURE_REGION_CHOICES = [
AZURE_RM_REGION_CHOICES = [
('eastus', _('US East')),
('eastus2', _('US East 2')),
('centralus', _('US Central')),
@ -810,23 +808,8 @@ AZURE_REGION_CHOICES = [
('koreacentral', _('Korea Central')),
('koreasouth', _('Korea South')),
]
AZURE_REGIONS_BLACKLIST = []
AZURE_RM_REGIONS_BLACKLIST = []
# Inventory variable name/value for determining whether a host is active
# in Microsoft Azure.
AZURE_ENABLED_VAR = 'instance_status'
AZURE_ENABLED_VALUE = 'ReadyRole'
# Filter for allowed group and host names when importing inventory from
# Microsoft Azure.
AZURE_GROUP_FILTER = r'^.+$'
AZURE_HOST_FILTER = r'^.+$'
AZURE_EXCLUDE_EMPTY_GROUPS = True
AZURE_INSTANCE_ID_VAR = 'private_id'
# --------------------------------------
# -- Microsoft Azure Resource Manager --
# --------------------------------------
AZURE_RM_GROUP_FILTER = r'^.+$'
AZURE_RM_HOST_FILTER = r'^.+$'
AZURE_RM_ENABLED_VAR = 'powerstate'

View File

@ -14,7 +14,7 @@
# W391 - Blank line at end of file
# W293 - Blank line contains whitespace
ignore=E201,E203,E221,E225,E231,E241,E251,E261,E265,E303,E501,W291,W391,W293
exclude=.tox,venv,awx/lib/site-packages,awx/plugins/inventory/ec2.py,awx/plugins/inventory/gce.py,awx/plugins/inventory/vmware.py,awx/plugins/inventory/windows_azure.py,awx/plugins/inventory/openstack.py,awx/ui,awx/api/urls.py,awx/main/migrations,awx/main/south_migrations,awx/main/tests/data,installer/openshift/settings.py
exclude=.tox,venv,awx/lib/site-packages,awx/plugins/inventory/ec2.py,awx/plugins/inventory/gce.py,awx/plugins/inventory/vmware.py,awx/plugins/inventory/openstack.py,awx/ui,awx/api/urls.py,awx/main/migrations,awx/main/south_migrations,awx/main/tests/data,installer/openshift/settings.py
[flake8]
ignore=E201,E203,E221,E225,E231,E241,E251,E261,E265,E303,E501,W291,W391,W293,E731,F405