예제 #1
0
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.')
예제 #2
0
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.')
예제 #4
0
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
예제 #5
0
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.')
예제 #6
0
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