A mockup of what an automated API Lifecycle could look like
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

215 lines
9.0 KiB

#!groovy
library identifier: '3scale-toolbox-jenkins@master',
retriever: modernSCM([$class: 'GitSCMSource',
remote: 'https://github.com/rh-integration/3scale-toolbox-jenkins.git',
traits: [[$class: 'jenkins.plugins.git.traits.BranchDiscoveryTrait']]])
def service = null
node() {
stage('Pre-requisites') {
if (params.OPENAPI_SPECIFICATION_FILE != "openapi-spec-v0.9.yaml"
&& params.OPENAPI_SPECIFICATION_FILE != "openapi-spec-v1.0.yaml"
&& params.OPENAPI_SPECIFICATION_FILE != "openapi-spec-v1.1.yaml"
&& params.OPENAPI_SPECIFICATION_FILE != "openapi-spec-v2.0.yaml") {
echo """
Please specify the OpenAPI Specification filename you want to deploy:
Use one of the following provided files:
- openapi-spec-v0.9.yaml => 2 methods, no security
- openapi-spec-v1.0.yaml => 2 methods, API Key
- openapi-spec-v1.1.yaml => 3 methods, API Key
- openapi-spec-v2.0.yaml => 3 methods, OpenID Connect
Use the OPENAPI_SPECIFICATION_FILE parameter to pass the OpenAPI Specification filename you want to deploy.
"""
error("Use the OPENAPI_SPECIFICATION_FILE parameter to pass the OpenAPI Specification filename you want to deploy.")
}
}
stage('Checkout Source') {
checkout scm
}
stage("Deploy API in Dev") {
// Prepare
service = toolbox.prepareThreescaleService(
openapi: [filename: "semver-usecase/" + params.OPENAPI_SPECIFICATION_FILE ],
environment: [ baseSystemName: "semver_usecase",
publicBasePath: "/api/",
environmentName: "dev",
oidcIssuerEndpoint: params.OIDC_ISSUER_ENDPOINT,
publicStagingWildcardDomain: params.PUBLIC_STAGING_WILDCARD_DOMAIN != "" ? params.PUBLIC_STAGING_WILDCARD_DOMAIN : null,
publicProductionWildcardDomain: params.PUBLIC_PRODUCTION_WILDCARD_DOMAIN != "" ? params.PUBLIC_PRODUCTION_WILDCARD_DOMAIN : null,
privateBaseUrl: params.PRIVATE_BASE_URL ],
toolbox: [ openshiftProject: params.NAMESPACE,
destination: params.TARGET_INSTANCE,
image: "quay.io/redhat/3scale-toolbox:master", // TODO: remove me once the final image is released
insecure: params.DISABLE_TLS_VALIDATION == "yes",
secretName: params.SECRET_NAME],
service: [:],
applications: [
[ name: "my-test-app", description: "This is used for tests", plan: "test", account: params.DEVELOPER_ACCOUNT_ID ]
],
applicationPlans: [
[ systemName: "test", name: "Test", defaultPlan: true, published: true ]
]
)
// Import OpenAPI
service.importOpenAPI()
echo "Service with system_name ${service.environment.targetSystemName} created !"
// Create an Application Plan
service.applyApplicationPlans()
// Create an Application
service.applyApplication()
// Run integration tests
runIntegrationTests(service)
// Promote to production
service.promoteToProduction()
}
stage("Deploy API in Test") {
// Prepare
service = toolbox.prepareThreescaleService(
openapi: [filename: "semver-usecase/" + params.OPENAPI_SPECIFICATION_FILE ],
environment: [ baseSystemName: "semver_usecase",
publicBasePath: "/api/",
environmentName: "test",
oidcIssuerEndpoint: params.OIDC_ISSUER_ENDPOINT,
publicStagingWildcardDomain: params.PUBLIC_STAGING_WILDCARD_DOMAIN != "" ? params.PUBLIC_STAGING_WILDCARD_DOMAIN : null,
publicProductionWildcardDomain: params.PUBLIC_PRODUCTION_WILDCARD_DOMAIN != "" ? params.PUBLIC_PRODUCTION_WILDCARD_DOMAIN : null,
privateBaseUrl: params.PRIVATE_BASE_URL ],
toolbox: [ openshiftProject: params.NAMESPACE,
destination: params.TARGET_INSTANCE,
image: "quay.io/redhat/3scale-toolbox:master", // TODO: remove me once the final image is released
insecure: params.DISABLE_TLS_VALIDATION == "yes",
secretName: params.SECRET_NAME],
service: [:],
applications: [
[ name: "my-test-app", description: "This is used for tests", plan: "test", account: params.DEVELOPER_ACCOUNT_ID ]
],
applicationPlans: [
[ systemName: "test", name: "Test", defaultPlan: true, published: true ]
]
)
// Import OpenAPI
service.importOpenAPI()
echo "Service with system_name ${service.environment.targetSystemName} created !"
// Create an Application Plan
service.applyApplicationPlans()
// Create an Application
service.applyApplication()
// Run integration tests
runIntegrationTests(service)
// Promote to production
service.promoteToProduction()
}
stage("Deploy API in Prod") {
// Prepare
service = toolbox.prepareThreescaleService(
openapi: [filename: "semver-usecase/" + params.OPENAPI_SPECIFICATION_FILE ],
environment: [ baseSystemName: "semver_usecase",
publicBasePath: "/api/",
environmentName: "prod",
oidcIssuerEndpoint: params.OIDC_ISSUER_ENDPOINT,
publicStagingWildcardDomain: params.PUBLIC_STAGING_WILDCARD_DOMAIN != "" ? params.PUBLIC_STAGING_WILDCARD_DOMAIN : null,
publicProductionWildcardDomain: params.PUBLIC_PRODUCTION_WILDCARD_DOMAIN != "" ? params.PUBLIC_PRODUCTION_WILDCARD_DOMAIN : null,
privateBaseUrl: params.PRIVATE_BASE_URL ],
toolbox: [ openshiftProject: params.NAMESPACE,
destination: params.TARGET_INSTANCE,
image: "quay.io/redhat/3scale-toolbox:master", // TODO: remove me once the final image is released
insecure: params.DISABLE_TLS_VALIDATION == "yes",
secretName: params.SECRET_NAME],
service: [:],
applications: [
[ name: "my-test-app", description: "This is used for tests", plan: "test", account: params.DEVELOPER_ACCOUNT_ID ]
],
applicationPlans: [
[ systemName: "test", name: "Test", defaultPlan: true, published: true ]
]
)
// Import OpenAPI
service.importOpenAPI()
echo "Service with system_name ${service.environment.targetSystemName} created !"
// Create an Application Plan
service.applyApplicationPlans()
// Create an Application
service.applyApplication()
// Run integration tests
runIntegrationTests(service)
// Promote to production
service.promoteToProduction()
}
}
def runIntegrationTests(def service) {
// To run the integration tests when using APIcast SaaS instances, we need
// to fetch the proxy definition to extract the staging public url
def proxy = service.readProxy("sandbox")
// The integration tests will be a bit different depending on the security scheme
// declared in the OpenAPI Specification file
def getCredentialsCodeSnippet = null
if (service.openapi.securityScheme.name() == "OPEN") {
getCredentialsCodeSnippet = """
credential_header="x-dummy: dummy"
echo "no credential will be used"
"""
} else if (service.openapi.securityScheme.name() == "APIKEY") {
def userkey = service.applications[0].userkey
getCredentialsCodeSnippet = """
credential_header="api-key: ${userkey}"
echo "userkey is ${userkey}"
"""
} else if (service.openapi.securityScheme.name() == "OIDC") {
def tokenEndpoint = getTokenEndpoint(params.OIDC_ISSUER_ENDPOINT)
def clientId = service.applications[0].clientId
def clientSecret = service.applications[0].clientSecret
getCredentialsCodeSnippet = """
echo "token endpoint is ${tokenEndpoint}"
echo "client_id=${clientId}"
echo "client_secret=${clientSecret}"
curl -sfk "${tokenEndpoint}" -d client_id="${clientId}" -d client_secret="${clientSecret}" -d scope=openid -d grant_type=client_credentials -o response.json
curl -sLfk https://github.com/stedolan/jq/releases/download/jq-1.6/jq-linux64 -o /tmp/jq
chmod 755 /tmp/jq
TOKEN="\$(/tmp/jq -r .access_token response.json)"
echo "Received access_token '\$TOKEN'"
credential_header="Authorization: Bearer \$TOKEN"
"""
}
// Run the actual tests
sh """set -e
echo "Public Staging Base URL is ${proxy.sandbox_endpoint}"
${getCredentialsCodeSnippet}
curl -sfk -w "GetLocation: %{http_code}\n" -o /dev/null "${proxy.sandbox_endpoint}/api/location" -H "\$credential_header"
curl -sfk -w "GetTimeframe: %{http_code}\n" -o /dev/null "${proxy.sandbox_endpoint}/api/timeframe" -H "\$credential_header"
# This one is only present in v1.1 and onwards
curl -sk -w "GetParticipants: %{http_code}\n" -o /dev/null "${proxy.sandbox_endpoint}/api/participants" -H "\$credential_header"
"""
}
def getTokenEndpoint(String oidcIssuerEndpoint) {
def m = (oidcIssuerEndpoint =~ /(https?:\/\/)[^:]+:[^@]+@(.*)/)
return "${m[0][1]}${m[0][2]}/protocol/openid-connect/token"
}