import { generateUuid } from "@azure/core-http" ; import { IRestResponse } from "typed-rest-client" ; import { Config } from "../../config" ; import { logger } from "../../logger" ; import { ServiceEndpointData } from "../../types" ; import { azdoUrl , getRestClient } from "../azdoClient" ; import { build as buildError } from "../errorBuilder" ; import { errorStatusCode } from "../errorStatusCode" ; import { AzureDevOpsOpts } from "../git" ; import { ServiceEndpoint , ServiceEndpointParams } from "./azdoInterfaces" ; const apiUrl = "_apis/serviceendpoint/endpoints" ; const apiVersion = "api-version=5.1-preview.2" ; param serviceEndpointData throws const validateServiceEndpointInput = ( serviceEndpointData ) : void => { const errors = [ ] ; if ( ! serviceEndpointData . name ) { errors . push ( `service end point name` ) ; } if ( ! serviceEndpointData . service_principal_id ) { errors . push ( `service prrincipla id` ) ; } if ( ! serviceEndpointData . service_principal_secret ) { errors . push ( `service prrincipla secret` ) ; } if ( ! serviceEndpointData . subscription_id ) { errors . push ( `subscription id` ) ; } if ( ! serviceEndpointData . subscription_name ) { errors . push ( `subscription name` ) ; } if ( ! serviceEndpointData . tenant_id ) { errors . push ( `tenant id` ) ; } if ( errors . length !== 0 ) { throw buildError ( errorStatusCode . AZURE_SERVICE_ENDPOINT , { errorKey : "service-endpoint-err-validation" , values : [ errors . join ( ", " ) ] , } ) ; } } ; param serviceEndpointData returns export const createServiceEndPointParams = ( serviceEndpointData ) : ServiceEndpointParams => { try { validateServiceEndpointInput ( serviceEndpointData ) ; const endPointParams = { authorization : { parameters : { authenticationType : "spnKey" , serviceprincipalid : serviceEndpointData . service_principal_id , serviceprincipalkey : serviceEndpointData . service_principal_secret , tenantid : serviceEndpointData . tenant_id , } , scheme : "ServicePrincipal" , } , data : { subscriptionId : serviceEndpointData . subscription_id , subscriptionName : serviceEndpointData . subscription_name , } , id : generateUuid ( ) , isReady : false , name : serviceEndpointData . name , type : "azurerm" , } ; return endPointParams ; } catch ( err ) { throw buildError ( errorStatusCode . AZURE_SERVICE_ENDPOINT , "service-endpoint-err-create-params" , err ) ; } } ; param serviceEndpointData param opts returns export const addServiceEndpoint = async ( serviceEndpointData , opts = { } ) : Promise < ServiceEndpoint > => { const message = `service endpoint ${ serviceEndpointData . name }` ; logger . info ( `addServiceEndpoint method called with ${ message }` ) ; const config = Config ( ) ; const { project = config . azure_devops && config . azure_devops . project , orgName = config . azure_devops && config . azure_devops . org , } = opts ; const orgUrl = azdoUrl ( orgName ! ) ; try { const endPointParams = createServiceEndPointParams ( serviceEndpointData ) ; logger . debug ( `Creating Service Endpoint with: ${ JSON . stringify ( endPointParams ) }` ) ; logger . info ( `Creating ${ message }` ) ; const client = await getRestClient ( opts ) ; const resource = `${ orgUrl }/${ project }/${ apiUrl }?${ apiVersion }` ; logger . debug ( ` addServiceEndpoint:Resource: ${ resource }` ) ; const resp = await client . create ( resource , endPointParams ) ; if ( resp === null || resp . statusCode !== 200 || resp . result === null ) { throw buildError ( errorStatusCode . AZURE_SERVICE_ENDPOINT , "service-endpoint-err-add" ) ; } logger . debug ( `Service Endpoint Response status code: status code: ${ resp . statusCode }}` ) ; logger . debug ( `Service Endpoint Response results: ${ JSON . stringify ( resp . result ) }` ) ; logger . info ( `Created Service Endpoint with id: ${ resp . result . id }` ) ; return resp . result ; } catch ( err ) { throw buildError ( errorStatusCode . AZURE_SERVICE_ENDPOINT , "service-endpoint-err-add-endpoint" , err ) ; } } ; param serviceEndpointName param opts returns export const getServiceEndpointByName = async ( serviceEndpointName , opts = { } ) : Promise < ServiceEndpoint | null > => { logger . info ( `getServiceEndpointByName called with ${ serviceEndpointName }` ) ; const config = Config ( ) ; const { project = config . azure_devops && config . azure_devops . project , orgName = config . azure_devops && config . azure_devops . org , } = opts ; const orgUrl = azdoUrl ( orgName ! ) ; logger . info ( `getServiceEndpointByName orgUrl: ${ orgUrl }` ) ; const uriParameter = `?endpointNames=${ serviceEndpointName }` ; const client = await getRestClient ( opts ) ; const resource = `${ orgUrl }/${ project }/${ apiUrl }${ uriParameter }&${ apiVersion }` ; logger . info ( `getServiceEndpointByName:Resource: ${ resource }` ) ; const resp = await client . get ( resource ) ; logger . debug ( `getServiceEndpointByName: Service Endpoint Response results: ${ JSON . stringify ( resp . result ) }` ) ; if ( resp === null || resp . result === null || resp . result . count === 0 ) { logger . info ( `Service Endpoint was not found by name: ${ serviceEndpointName }` ) ; return null ; } if ( resp . result . count > 1 ) { throw buildError ( errorStatusCode . AZURE_SERVICE_ENDPOINT , { errorKey : "service-endpoint-err-get-endpoint-multiple" , values : [ resp . result . count . toString ( ) , serviceEndpointName ] , } ) ; } const endpoints = resp . result . value as ServiceEndpoint [ ] ; logger . info ( `Found Service Endpoint by name ${ serviceEndpointName } with a id ${ endpoints [ 0 ] . id }` ) ; return endpoints [ 0 ] ; } ; param serviceEndpointData param opts returns export const createServiceEndpointIfNotExists = async ( serviceEndpointData , opts = { } ) : Promise < ServiceEndpoint > => { const serviceEndpointName = serviceEndpointData . name ; if ( ! serviceEndpointName ) { throw buildError ( errorStatusCode . AZURE_SERVICE_ENDPOINT , "service-endpoint-err-create-missing-name" ) ; } try { let serviceEndpoint = await getServiceEndpointByName ( serviceEndpointName , opts ) ; if ( serviceEndpoint === null || serviceEndpoint === undefined ) { serviceEndpoint = await addServiceEndpoint ( serviceEndpointData , opts ) ; } return serviceEndpoint ; } catch ( err ) { throw buildError ( errorStatusCode . AZURE_SERVICE_ENDPOINT , "service-endpoint-err-create" , err ) ; } } ; interface ServiceEndpointByNameResult { count : number ; value : ServiceEndpoint [ ] ; }