Browse Source

pif paf pouf

master
Nicolas Massé 6 years ago
parent
commit
6bf5d05851
  1. 1
      .gitignore
  2. 216
      Jenkinsfile
  3. 57
      README.md
  4. 87
      cleanup/cleanup.yml

1
.gitignore

@ -3,3 +3,4 @@
.settings
.project
target
*.retry

216
Jenkinsfile

@ -0,0 +1,216 @@
#!groovy
library identifier: '3scale-toolbox-jenkins@openapi3',
retriever: modernSCM([$class: 'GitSCMSource',
remote: 'https://github.com/nmasse-itix/3scale-toolbox-jenkins.git',
traits: [[$class: 'jenkins.plugins.git.traits.BranchDiscoveryTrait']]])
def service = null
node("maven") {
stage('Checkout Source') {
checkout scm
//git url: "https://github.com/nmasse-itix/library-api.git"
}
stage('Pre-requisites') {
if (! fileExists('openapi.json')) {
echo """
There is no OpenAPI Specification file!
"""
error("Nothing to deploy!")
}
// Install pre-requisites
sh """
curl -L -o /tmp/jq https://github.com/stedolan/jq/releases/download/jq-1.6/jq-linux64
chmod 755 /tmp/jq
"""
}
stage("Deploy API in Dev") {
// Prepare
service = toolbox.prepareThreescaleService(
openapi: [filename: "openapi.json" ],
environment: [ baseSystemName: "library",
environmentName: "dev",
oidcIssuerEndpoint: params.OIDC_ISSUER_ENDPOINT,
publicBasePath: "/",
privateBasePath: "/",
privateBaseUrl: params.PRIVATE_BASE_URL ],
toolbox: [ openshiftProject: params.NAMESPACE,
destination: params.TARGET_INSTANCE,
image: "quay.io/redhat/3scale-toolbox:v0.16.2",
activeDeadlineSeconds: 180,
insecure: params.DISABLE_TLS_VALIDATION == "yes",
secretName: params.SECRET_NAME],
service: [:],
applications: [
[ name: "petstore-app", description: "This is used for tests", plan: "test", account: "john" ]
],
applicationPlans: [
[ systemName: "test", name: "Test", defaultPlan: true, published: true ]
]
)
// A pre-release version needs to use the mock backend
//if (service.openapi.majorVersion == "0") {
// service.environment.privateBaseUrl = params.MOCK_SERVER
// service.environment.privateBasePath = params.MOCK_URL
//}
// Import OpenAPI
service.importOpenAPI()
echo "Service with system_name ${service.environment.targetSystemName} created !"
// Create an Application Plan
service.applyApplicationPlans()
// Create an Application
service.applyApplication()
// Promote to production
service.promoteToProduction()
}
// Terminate the pipeline earlier if the API is not yet production ready
if (service.openapi.majorVersion == "0") {
currentBuild.result = 'SUCCESS'
return
}
stage("Deploy API in Test") {
// Prepare
service = toolbox.prepareThreescaleService(
openapi: [filename: "openapi.json" ],
environment: [ baseSystemName: "library",
environmentName: "test",
oidcIssuerEndpoint: params.OIDC_ISSUER_ENDPOINT,
publicBasePath: "/",
privateBasePath: "/",
privateBaseUrl: params.PRIVATE_BASE_URL ],
toolbox: [ openshiftProject: params.NAMESPACE,
destination: params.TARGET_INSTANCE,
image: "quay.io/redhat/3scale-toolbox:v0.16.2",
activeDeadlineSeconds: 180,
insecure: params.DISABLE_TLS_VALIDATION == "yes",
secretName: params.SECRET_NAME],
service: [:],
applications: [
[ name: "petstore-app", description: "This is used for tests", plan: "test", account: "john" ]
],
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: "openapi.json" ],
environment: [ baseSystemName: "library",
environmentName: "prod",
oidcIssuerEndpoint: params.OIDC_ISSUER_ENDPOINT,
publicBasePath: "/",
privateBasePath: "/",
privateBaseUrl: params.PRIVATE_BASE_URL ],
toolbox: [ openshiftProject: params.NAMESPACE,
destination: params.TARGET_INSTANCE,
image: "quay.io/redhat/3scale-toolbox:v0.16.2",
activeDeadlineSeconds: 180,
insecure: params.DISABLE_TLS_VALIDATION == "yes",
secretName: params.SECRET_NAME],
service: [:],
applications: [
[ name: "petstore-app", description: "This is used for tests", plan: "silver", account: "john" ]
],
applicationPlans: [
[ systemName: "gold", name: "Gold", defaultPlan: false, published: true ],
[ systemName: "silver", name: "Silver", 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()
// 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
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 "findPets: %{http_code}\n" -o /dev/null "${proxy.sandbox_endpoint}/pets" -H "\$credential_header"
curl -sfk -w "findPetById: %{http_code}\n" -o /dev/null "${proxy.sandbox_endpoint}/pets/1" -H "\$credential_header"
# This one is only present in v1.1 and onwards
curl -sk -w "updatePet: %{http_code}\n" -o /dev/null "${proxy.sandbox_endpoint}/pets/1" -H "Content-Type: application/json" -XPUT -d '{"id":1,"name":"Raspoutine","tag":"dog"}' -H "\$credential_header"
"""
}
def getTokenEndpoint(String oidcIssuerEndpoint) {
def m = (oidcIssuerEndpoint =~ /(https?:\/\/)[^:]+:[^@]+@(.*)/)
return "${m[0][1]}${m[0][2]}/protocol/openid-connect/token"
}

57
README.md

@ -1,11 +1,58 @@
# Library API
```
## Setup
Create a project and deploy the Library API Backend.
```sh
oc new-project library-api
oc create secret generic 3scale-toolbox -n library-api --from-file="$HOME/.3scalerc.yaml"
oc new-app -n library-api --template=jenkins-ephemeral --name=jenkins -p MEMORY_LIMIT=2Gi
oc set env -n library-api dc/jenkins JENKINS_OPTS=--sessionTimeout=86400
oc import-image openjdk-8-rhel8 --from=registry.redhat.io/openjdk/openjdk-8-rhel8 --confirm -n openshift --reference-policy=local
oc import-image -n openshift openjdk-8-rhel8 --from=registry.redhat.io/openjdk/openjdk-8-rhel8 --confirm --reference-policy=local
oc new-app -n library-api -i openjdk-8-rhel8 https://github.com/nmasse-itix/library-api.git --name=library-api
oc expose -n library-api svc/library-api --hostname="library-api.apps.ocp4.itix.fr"
```
Deploy a Jenkins master.
```sh
oc new-app -n library-api --template=jenkins-ephemeral --name=jenkins -p MEMORY_LIMIT=2Gi
oc set env -n library-api dc/jenkins JENKINS_OPTS=--sessionTimeout=86400
```
Create a secret containing your 3scale toolbox remotes.
```sh
oc create -n library-api secret generic 3scale-toolbox --from-file="$HOME/.3scalerc.yaml"
```
Add a new Build Config to run the Jenkins pipeline.
```sh
oc new-build -n library-api --strategy=pipeline --name=library-pipeline https://github.com/nmasse-itix/library-api.git -e PRIVATE_BASE_URL=http://library-api.apps.ocp4.itix.fr -e NAMESPACE=library-api -e TARGET_INSTANCE=3scale-saas -e SECRET_NAME=3scale-toolbox -e OIDC_ISSUER_ENDPOINT=https://zync:[REDACTED]@sso.apps.ocp4.itix.fr/auth/realms/3scale-saas -e DISABLE_TLS_VALIDATION=yes -e MOCK_SERVER=https://microcks.apps.ocp4.itix.fr -e MOCK_URL=/rest/Library/0.9.0
```
## Reset
Remove the Jenkins pipeline:
```sh
oc delete -n library-api bc/library-pipeline
```
Remove the 3scale services:
```sh
ansible-playbook cleanup/cleanup.yml -e admin_portal_hostname=[TENANT]-admin.3scale.net -e threescale_token=[REDACTED]
```
Go to the [Apicurio Studio](https://apicurio-studio.app.itix.fr/apis) and remove the **Library** service.
Go to the Microcks console and remove the **Library** service.
Set the OpenAPI Specification file back to version 0.9:
```sh
mv api-contracts/openapi-0.9.json openapi.json
git add openapi.json
git commit -m 'reset the demo'
git push
```

87
cleanup/cleanup.yml

@ -0,0 +1,87 @@
---
- name: Delete petstore services of a 3scale tenant
hosts: localhost
gather_facts: no
vars:
ansible_connection: local
threescale_api: https://{{ admin_portal_hostname }}/admin/api
find_in_systemname: library
validate_certs: no
tasks:
- assert:
that:
- threescale_token is defined
- admin_portal_hostname is defined
msg: >
Please pass your 3scale Access Token in the 'threescale_token' extra var
and your 3scale Admin Portal hostname in the 'admin_portal_hostname' extra var.
- name: Find Services
uri:
url: '{{ threescale_api }}/services.json?access_token={{ threescale_token }}'
validate_certs: '{{ validate_certs }}'
register: find_services_response
changed_when: false
- name: Delete all matching services
uri:
url: '{{ threescale_api }}/services/{{ item.id }}.json?access_token={{ threescale_token }}'
method: DELETE
status_code: "200,404"
validate_certs: '{{ validate_certs }}'
register: delete_service_response
changed_when: delete_service_response.status == 200
with_items: '{{ services }}'
when: >
find_in_systemname in item.system_name
vars:
services: '{{ find_services_response.json|json_query(query) }}'
query: >
services[?service.system_name != `api`].{"id": service.id, "system_name": service.system_name}
- name: Find API Backends
uri:
url: '{{ threescale_api }}/backend_apis.json?access_token={{ threescale_token }}'
validate_certs: '{{ validate_certs }}'
register: find_backends_response
changed_when: false
- name: Delete all matching API Backends
uri:
url: '{{ threescale_api }}/backend_apis/{{ item.id }}.json?access_token={{ threescale_token }}'
method: DELETE
status_code: "200,404"
validate_certs: '{{ validate_certs }}'
register: delete_service_response
changed_when: delete_service_response.status == 200
with_items: '{{ services }}'
when: >
find_in_systemname in item.system_name
vars:
services: '{{ find_backends_response.json|json_query(query) }}'
query: >
backend_apis[?backend_api.system_name != `api`].{"id": backend_api.id, "system_name": backend_api.system_name}
- name: Find ActiveDocs
uri:
url: '{{ threescale_api }}/active_docs.json?access_token={{ threescale_token }}'
validate_certs: '{{ validate_certs }}'
register: find_active_docs_response
changed_when: false
- name: Delete all matching ActiveDocs
uri:
url: '{{ threescale_api }}/active_docs/{{ item.id }}.json?access_token={{ threescale_token }}'
method: DELETE
status_code: "200,404"
validate_certs: '{{ validate_certs }}'
register: delete_active_docs_response
changed_when: delete_active_docs_response.status == 200
with_items: '{{ active_docs }}'
when: >
find_in_systemname in item.system_name
vars:
active_docs: '{{ find_active_docs_response.json|json_query(query) }}'
query: >
api_docs[?api_doc.system_name != `echo`].{"id": api_doc.id, "system_name": api_doc.system_name}
Loading…
Cancel
Save