示例#1
0
def connect_jenkins(account=None):
    if account is None:
        config_document = get_db_config()
        account = dict()
        account['url'] = config_document['jenkins_url']
        account['username'] = config_document['jenkins_user']
        account['password'] = config_document['jenkins_pass']
    return JenkinsAPI(account['url'], account['username'], account['password'])
示例#2
0
def pipeline_create():
    """
    Setup a pipeline for an SCM project with a specific branch
    This endpoint is used by the DevOps admin
    At the end of successful execution, a Jenkins pipeline for the SCM project is created with required build parameters
    ---
    tags:
      - pipeline
    parameters:
      - in: path
        name: scm-url
        required: true
        description: SCM url for this project
        type: string
      - in: path
        name: scm-branch
        required: true
        description: SCM branch for this project
        type: string
      - in: path
        name: export-policy
        required: false
        description: export-policy for this project
        type: string
    responses:
      200:
        description: Pipeline has been created successfully

    """
    #####
    # 1. Validate input form parameters
    # 2. Get config document for setting up the pipeline details
    # 3. Gather storage details for creating PVC for this pipeline
    # 4. Create a Kube PVC (Trident creates a PV and an ONTAP volume, maps it to this PVC. We manage only the PVCs)
    # 5. Create Jenkins job
    # 6. Setup Jenkins purge job for this pipeline
    # 7. Record all pipeline details in database
    #####
    # Validate input web form parameters from the application
    _validate_input_form_params(request.form, ['scm-branch', 'scm-url'])

    connect, config = _get_config_from_db()

    # Gather storage details for creating PVC
    scm_project_url = helpers.sanitize_scm_url(request.form['scm-url'])
    if scm_project_url is None:
        raise GenericException(406, "Invalid SCM URL provided")
    pipeline = {
        'name':
        '-'.join([
            'pipeline',
            helpers.extract_name_from_git_url(request.form['scm-url']),
            request.form['scm-branch']
        ]),
        'export_policy':
        request.form.get(
            'export-policy',
            'default'),  # set default export policy if not specified
        'scm_url':
        scm_project_url
    }

    # Create PVC. Once we create a Kube PVC, Trident creates an ONTAP volume and a PV for this PVC
    kube = KubernetesAPI.get_instance()
    vol_size = "10000"  # set default vol size to 10Gig, 10000 in MB
    # TODO: Change this to default SC from Kube -- list_all_storage_classes and read annotations to find default
    storage_class = config.get('storage_class')
    if storage_class == '':
        storage_class = None  # Don't set SC if SC is not passed in Helm, so that Kube can use the default storage class
    pvc_response = kube.create_pvc_resource(vol_name=pipeline['name'],
                                            vol_size=vol_size,
                                            storage_class=storage_class)
    if not helpers.verify_successful_response(pvc_response):
        raise GenericException(500, "Kubernetes PVC creation error")
    if pvc_response['phase'] != 'Bound':
        raise GenericException(500, "Kubernetes PVC cannot be bound")

    # setup params for Jenkins pipeline job
    pipeline_job = helpers.set_jenkins_job_params('ci-pipeline')
    pipeline_job['volume_claim_name'] = pvc_response['name']
    pipeline_job['scm_url'] = request.form['scm-url']
    pipeline_job['scm_branch'] = request.form['scm-branch']
    pipeline_job['kube_namespace'] = config['kube_namespace']

    # TODO: should this volume_name be populated as part of pvc_response? -
    #  but might want to handle if PVC creation has failed in KubernetesAPI.py
    pipeline_job['volume_name'] = kube.get_volume_name_from_pvc(
        pvc_response['name'])  # Get associated volume with PVC
    # TODO: This cannot be None.
    #  Validate after bootstrapping, PVCs for all services to be part of the config document.
    #  Remove this after including validation
    if config.get('scm_pvc_name') is None:
        pipeline_job['scm_volume_claim'] = kube.get_kube_resource_name(
            config['scm_volume'], 'pvc')

    purge_job = helpers.set_jenkins_job_params(
        'trigger-purge')  # setup params for Jenkins purge job
    purge_job['kube_namespace'] = config['kube_namespace']

    # Create Jenkins CI and purge jobs for this pipeline
    # If Jenkins connection fails, delete the Kube PVC created from previous step
    try:
        jenkins = JenkinsAPI(config['jenkins_url'], config['jenkins_user'],
                             config['jenkins_pass'])
    except Exception as exc:
        KubernetesAPI.get_instance().delete_pvc(pvc_response['name'])
        raise GenericException(500, "Jenkins connection error: %s" % str(exc))
    # If job creation fails, delete the Kube PVC created from previous step
    try:
        jenkins_job_url = jenkins.create_job(job_name=pipeline['name'],
                                             params=pipeline_job,
                                             form_fields=request.form)
        jenkins.create_job(job_name='purge_policy_enforcer',
                           params=purge_job,
                           form_fields=None)
    except Exception as exc:
        KubernetesAPI.get_instance().delete_pvc(pvc_response['name'])
        traceback.print_exc()
        raise GenericException(500,
                               "Jenkins Job Creation Error: %s" % str(exc))

    # Complete gathering pipeline details
    pipeline['pvc'] = pvc_response['name']
    pipeline['volume'] = pipeline_job['volume_name']
    pipeline['jenkins_url'] = jenkins_job_url

    # Record new pipeline in database
    # TODO: type=pipeline document
    try:
        new_pipeline_document = Pipeline(**pipeline)
        new_pipeline_document.store(connect)
    except Exception as exc:
        # If DB operation fails, delete the Jenkins pipeline job, purge job and Kube PVC created from previous step
        jenkins.delete_job(pipeline['name'])
        KubernetesAPI.get_instance().delete_pvc(pvc_response['name'])
        raise GenericException(
            500,
            "Error recording new project in the DB, please contact your administrator",
            "Database Exception" + str(exc))

    # TODO: Can we do a better in-page rendering instead of navigating to a raw JSON msg?
    return jsonify({'project_name': pipeline['name']}), 200
示例#3
0
def project_create():
    """
    create project
    ---
    tags:
      - project
    parameters:
      - in: path
        name: scm-url
        required: true
        description: git url for this project
        type: string
      - in: path
        name: scm-branch
        required: true
        description: git branch for this project
        type: string
      - in: path
        name: export-policy
        required: false
        description: export-policy for this project
        type: string
    responses:
      200:
        description: project was created successfully

    """
    # Retrieve customer configuration document from database

    try:
        database = helpers.connect_db()
        config_document = helpers.get_db_config()
    except Exception as e:
        raise GenericException(
            500,
            "Customer configuration document not found, please contact your administrator",
            "Database Exception")
    if not config_document:
        raise GenericException(
            500,
            "Customer configuration document not found, please contact your administrator",
            "Database Exception")
    expected_keys = ['scm-branch', 'scm-url']
    if not helpers.request_validator(request.form, expected_keys):
        raise GenericException(400, "SCM URL and SCM Branch are required")

    scm_project_url = helpers.sanitize_scm_url(request.form['scm-url'])

    if scm_project_url is None:
        raise GenericException(406, "Invalid SCM URL provided")

    project_name = helpers.extract_name_from_git_url(request.form['scm-url'])
    project_name += "-" + request.form['scm-branch']
    # Kubernetes does not like _
    project_name = helpers.replace_kube_invalid_characters(project_name)
    # ONTAP does not like -
    project_name_no_dashes = helpers.replace_ontap_invalid_char(project_name)

    ontap_instance = OntapService(config_document['ontap_api'],
                                  config_document['ontap_apiuser'],
                                  config_document['ontap_apipass'],
                                  config_document['ontap_svm_name'],
                                  config_document['ontap_aggr_name'],
                                  config_document['ontap_data_ip'])
    ontap_data_ip = ontap_instance.data_ip
    vol_uid = "0"
    vol_gid = "0"
    vol_size = "10000"
    if 'export_policy' in request.form:
        vol_export_policy = request.form['export-policy']
    else:
        vol_export_policy = 'default'
    try:
        status, vol_size = ontap_instance.create_volume(
            project_name_no_dashes, vol_size, vol_uid, vol_gid,
            vol_export_policy)
    except Exception as e:
        error_message = "Unable to create backing ontap volume for pipeline"
        logging.error(
            "Unable to create backing ontap volume for pipeline:\n %s" %
            traceback.format_exc())
        raise GenericException(500, error_message)

    if not helpers.verify_successful_response(status):
        error_message = "Unable to create backing ontap volume for pipeline: "
        try:
            error = status[0]['error_message'].split('(', 1)[0]
        except KeyError:
            error = ''
        error_message = error_message + error
        raise GenericException(500, error_message)

    # if volume creation successful, autosupport log
    # display a warning if this step fails , we don't want to exit out
    try:
        pass
        # helpers.autosupport(project_name_no_dashes, vol_size)
    except Exception as e:
        logging.warning("WARNING: Unable to generate autosupport log (%s)  " %
                        str(e))

    kube_namespace = 'default'
    pv_and_pvc_responses = KubernetesAPI().create_pv_and_pvc(
        project_name, vol_size, kube_namespace, ontap_data_ip)

    for response in pv_and_pvc_responses:
        status.append(response)

    if not helpers.verify_successful_response(status):
        raise GenericException(500, "Kubernetes PV/PVC Error")

    try:
        jenkins = JenkinsAPI(config_document['jenkins_url'],
                             config_document['jenkins_user'],
                             config_document['jenkins_pass'])
    except Exception as exc:
        raise GenericException(500, "Jenkins connection error: %s" % str(exc))
    params = dict()
    params['type'] = 'ci-pipeline'
    params['volume_name'] = project_name_no_dashes
    params['git_volume'] = config_document['git_volume']
    params['service_username'] = config_document['service_username']
    params['service_password'] = config_document['service_password']
    params['broker_url'] = config_document['web_service_url']
    params['container_registry'] = config_document['container_registry']

    try:
        jenkins.create_job(project_name, params, request.form)
    except Exception as exc:
        raise GenericException(500,
                               "Jenkins Job Creation Error: %s" % str(exc))

    jenkins_url = config_document['jenkins_url'] + "job/" + project_name
    # Record new project in database
    try:
        new_project_document = Project(name=project_name,
                                       volume=project_name_no_dashes,
                                       export_policy=vol_export_policy,
                                       scm_url=scm_project_url,
                                       jenkins_url=jenkins_url)
        new_project_document.store(database)
    except Exception as exc:
        raise GenericException(
            500, "Error recording new project in the DB, \
                               please contact your administrator",
            "Database Exception" + str(exc))
    # create trigger-purge jenkins job if not already done
    jenkins_account = dict()
    jenkins_account['url'] = config_document['jenkins_url']
    jenkins_account['username'] = config_document['jenkins_user']
    jenkins_account['password'] = config_document['jenkins_pass']

    try:
        helpers.create_purge_jenkins_job(job='purge_policy_enforcer',
                                         account=jenkins_account)
    except RuntimeError as exc:
        raise GenericException(
            500, "Jenkins Job Creation Error: 'purge_policy_enforcer' ")
    # need not return project_volume once we start storing volume info in DB
    return jsonify({
        'project_name': project_name,
        'project_volume': project_name_no_dashes
    }), 200