def get_container_registry_service_connection(organization, project): import subprocess import json subscription_id, subscription_name, tenant_id, _environment_name = get_default_subscription_info( ) logger.warning( "Using your default Azure subscription %s for fetching Azure Container Registries.", subscription_name) acr_list = subprocess.check_output('az acr list -o json', shell=True) acr_list = json.loads(acr_list) if acr_list: registry_choice = 0 registry_choice_list = [] for acr_clusters in acr_list: registry_choice_list.append(acr_clusters['name']) registry_choice = prompt_user_friendly_choice_list( "Which Azure Container Registry do you want to use for this pipeline?", registry_choice_list) selected_registry = acr_list[registry_choice] cix_client = get_new_cix_client(organization=organization) acr_connection_obj = get_container_registry_connection_create_object( subscription_id, subscription_name, tenant_id, selected_registry['id'], selected_registry['name'], selected_registry['loginServer']) acr_container_resource = cix_client.create_resources( creation_parameters=acr_connection_obj, project=project) poll_connection_ready( organization, project, acr_container_resource.resources['containerRegistryConnection'] ['Id']) return acr_container_resource.resources['containerRegistryConnection'] raise CLIError( 'There is no Azure container registry associated with your subscription. ' 'Create an ACR or switch to another subscription, ' 'verify with command \'az acr list\' and try again.')
def get_kubernetes_namespace(organization, project, cluster, subscription_id, subscription_name, tenant_id, azure_env): choice_list = [] existing_namespace_list = [] choice_list.append("Create new") se_request_obj = get_se_kubernetes_namespace_request_obj( subscription_id, subscription_name, cluster['id'], cluster['name'], cluster['fqdn'], azure_env, tenant_id) se_client = get_service_endpoint_client(organization=organization) se_result = se_client.execute_service_endpoint_request( service_endpoint_request=se_request_obj, project=project, endpoint_id=cluster['name']) if se_result.result: import json for namespace in se_result.result: ns_json_obj = json.loads(namespace) existing_namespace_list.append(ns_json_obj['Value']) choice_list.append(ns_json_obj['Value']) choice = prompt_user_friendly_choice_list( "Which kubernetes namespace do you want to target?", choice_list) if choice == 0: create_namespace = True namespace = prompt_not_empty( "Enter a name for new namespace to create: ") print('') else: create_namespace = False namespace = existing_namespace_list[choice - 1] return create_namespace, namespace
def push_files_to_repository(organization, project, repo_name, branch, files, repository_type): commit_strategy_choice_list = ['Commit directly to the {branch} branch.'.format(branch=branch), 'Create a new branch for this commit and start a pull request.'] commit_choice = prompt_user_friendly_choice_list("How do you want to commit the files to the repository?", commit_strategy_choice_list) commit_direct_to_branch = commit_choice == 0 if repository_type == _GITHUB_REPO_TYPE: return push_files_github(files, repo_name, branch, commit_direct_to_branch) if repository_type == _AZURE_GIT_REPO_TYPE: return push_files_to_azure_repo(files, repo_name, branch, commit_direct_to_branch, organization, project) raise CLIError('File push failed: Repository type not supported.')
def get_github_service_endpoint(organization, project): """ This will try to create a GitHub service connection if there is no existing one in the project GitHub pat token will be asked for interactively or can be provided by setting the Environment variable AZ_DEVOPS_GITHUB_PAT_ENVKEY. Service endpoint connection name is asked as input from the user """ from azext_devops.dev.common.identities import get_current_identity, get_account_from_identity authenticated_user_unique_id = get_account_from_identity( get_current_identity(organization)) se_client = get_service_endpoint_client(organization) existing_service_endpoints = _get_service_endpoints( organization, project, 'github') service_endpoints_choice_list = ['Create new GitHub service connection'] github_service_endpoints = [] choice = 0 for endpoint in existing_service_endpoints: if (endpoint.authorization.scheme == 'InstallationToken' or authenticated_user_unique_id == endpoint.created_by.unique_name): service_endpoints_choice_list.append('{}'.format(endpoint.name)) github_service_endpoints.append(endpoint) if github_service_endpoints: choice = prompt_user_friendly_choice_list( "Which service connection do you want to use to communicate with GitHub?", service_endpoints_choice_list) if choice > 0: logger.debug('Using service endpoint index (%s) name (%s)', choice, github_service_endpoints[choice - 1].name) return github_service_endpoints[choice - 1].id logger.debug("Creating a new service endpoint.") github_pat = get_github_pat_token() se_name = prompt_not_empty('Enter a service connection name to create? ') print('') service_endpoint_authorization = EndpointAuthorization( parameters={'accessToken': github_pat}, scheme='PersonalAccessToken') service_endpoint_to_create = ServiceEndpoint( authorization=service_endpoint_authorization, name=se_name, type='github', url='https://github.com/') return se_client.create_service_endpoint(service_endpoint_to_create, project).id
def get_kubernetes_environment_resource(organization, project, repo_name): logger.debug("Creating a new k8s environment resource.") import subprocess import json subscription_id, subscription_name, tenant_id, environment_name = get_default_subscription_info( ) logger.warning( "Using your default Azure subscription %s for fetching AKS clusters.", subscription_name) aks_list = subprocess.check_output('az aks list -o json', shell=True) aks_list = json.loads(aks_list) if aks_list: cluster_choice = 0 cluster_choice_list = [] for aks_clusters in aks_list: cluster_choice_list.append(aks_clusters['name']) cluster_choice = prompt_user_friendly_choice_list( "Which kubernetes cluster do you want to target for this pipeline?", cluster_choice_list) selected_cluster = aks_list[cluster_choice] create_namespace, namespace = get_kubernetes_namespace( organization, project, selected_cluster, subscription_id, subscription_name, tenant_id, environment_name) kubernetes_connection_obj = get_kubernetes_connection_create_object( subscription_id, subscription_name, selected_cluster['id'], selected_cluster['name'], selected_cluster['fqdn'], tenant_id, namespace, create_namespace, environment_name) cix_client = get_new_cix_client(organization=organization) kubernetes_connection = cix_client.create_resources( creation_parameters=kubernetes_connection_obj, project=project) k8s_connection_obj = kubernetes_connection.resources['k8sConnection'] poll_connection_ready(organization, project, k8s_connection_obj['Id']) kubernetes_env_obj = get_kubernetes_resource_create_object( k8s_connection_obj['Name'], selected_cluster['name'], repo_name, k8s_connection_obj['Id'], namespace) kubernetes_environment_resource = cix_client.create_resources( creation_parameters=kubernetes_env_obj, project=project) return kubernetes_environment_resource.resources['k8sResource'] raise CLIError( 'There are no AKS clusters under your subscription. ' 'Create the clusters or switch to another subscription, verify with ' 'command \'az aks list\' and try again.')
def get_webapp_from_list_selection(): logger.debug("Fetching web app list to display") import subprocess import json _subscription_id, subscription_name, _tenant_id, _environment_name = get_default_subscription_info( ) logger.warning( "Using your default Azure subscription %s for fetching Web App list.", subscription_name) webapp_list = subprocess.check_output('az webapp list -o json', shell=True) webapp_list = json.loads(webapp_list) if webapp_list: app_choice = 0 app_choice_list = [] for webapp in webapp_list: app_choice_list.append(webapp['name']) app_choice = prompt_user_friendly_choice_list( "Which Web App do you want to target?", app_choice_list) return webapp_list[app_choice]['name'] raise CLIError( 'There are no Web apps in this subscription. Either create a Web App using this subscription ' 'or change to another subscription. Verify with command \'az webapp list\'.' )
def _create_and_get_yml_path( cix_client, repository_type, repo_id, repo_name, branch, # pylint: disable=too-many-locals, too-many-statements service_endpoint, project, organization): logger.debug( 'No yaml file was given. Trying to find the yaml file in the repo.') queue_branch = branch default_yml_exists = False yml_names = [] yml_options = [] configurations = cix_client.get_configurations( project=project, repository_type=repository_type, repository_id=repo_id, branch=branch, service_connection_id=service_endpoint) for configuration in configurations: if configuration.path.strip('/') == 'azure-pipelines.yml': default_yml_exists = True logger.debug('The repo has a yaml pipeline definition. Path: %s', configuration.path) custom_name = 'Existing yaml (path={})'.format(configuration.path) yml_names.append(custom_name) yml_options.append( YmlOptions(name=custom_name, content=configuration.content, id='customid', path=configuration.path)) recommendations = cix_client.get_template_recommendations( project=project, repository_type=repository_type, repository_id=repo_id, branch=branch, service_connection_id=service_endpoint) logger.debug('List of recommended templates..') # sort recommendations from operator import attrgetter recommendations = sorted(recommendations, key=attrgetter('recommended_weight'), reverse=True) for recommendation in recommendations: yml_names.append(recommendation.name) yml_options.append( YmlOptions(name=recommendation.name, content=recommendation.content, id=recommendation.id, description=recommendation.description, params=recommendation.parameters, assets=recommendation.assets)) temp_filename = None files = [] yml_selection_index = 0 proceed_selection = 1 while proceed_selection == 1: proceed_selection = 0 # Clear files since user can change the template now del files[:] yml_selection_index = prompt_user_friendly_choice_list( "Which template do you want to use for this pipeline?", yml_names) if yml_options[yml_selection_index].params: yml_options[yml_selection_index].content, yml_options[ yml_selection_index].assets = _handle_yml_props( params_required=yml_options[yml_selection_index].params, template_id=yml_options[yml_selection_index].id, cix_client=cix_client, repo_name=repo_name, organization=organization, project=project) temp_dir = tempfile.mkdtemp(prefix='AzurePipelines_') temp_filename = os.path.join(temp_dir, 'azure-pipelines.yml') f = open(temp_filename, mode='w') f.write(yml_options[yml_selection_index].content) f.close() assets = yml_options[yml_selection_index].assets if assets: for asset in assets: files.append(Files(asset.destination_path, asset.content)) view_choice = prompt_user_friendly_choice_list( 'Do you want to view/edit the template yaml before proceeding?', ['Continue with generated yaml', 'View or edit the yaml']) if view_choice == 1: open_file(temp_filename) proceed_selection = prompt_user_friendly_choice_list( 'Do you want to proceed creating a pipeline?', ['Proceed with this yaml', 'Choose another template']) # Read updated data from the file f = open(temp_filename, mode='r') content = f.read() f.close() delete_dir(temp_dir) checkin_path = 'azure-pipelines.yml' if default_yml_exists and not yml_options[ yml_selection_index].path: # We need yml path from user logger.warning( 'A yaml file azure-pipelines.yml already exists in the repository root.' ) checkin_path = prompt_not_empty( msg= 'Enter a yaml file path to checkin the new pipeline yaml in the repository? ', help_string= 'e.g. /new_azure-pipeline.yml to add in the root folder.') print('') files.append(Files(checkin_path, content)) print('Files to be added to your repository ({numfiles})'.format( numfiles=len(files))) count_file = 1 for file in files: print('{index}) {file}'.format(index=count_file, file=file.path)) count_file = count_file + 1 print('') if default_yml_exists and checkin_path.strip('/') == 'azure-pipelines.yml': print('Edits on the existing yaml can be done in the code repository.') else: queue_branch = push_files_to_repository(organization, project, repo_name, branch, files, repository_type) return checkin_path, queue_branch