In this article, we present a no-code based solution to create a mock endpoint based on an OpenAPI spec (specification) and that can be used by an Apigee API proxy as a target endpoint during development phases.
Considering a valid Open API spec (based on version v2 or v3.x), our requirements are:
In this article we use an API proxy example based on Apigee X/hybrid but the mocking solution does not depend on the Apigee runtime option that is used.
For Apigee Edge customers willing to implement the solution described in this article, it is important to consider authenticating Apigee via Service Account Keys, as described in option-2 of the Apigee community article: “Hosted Targets vs. Google Cloud Run”.
The mock service on GCP will be deployed on Google Cloud Run.
Here is an Apigee devrel reference implementation for how to front a Cloud Run service with Apigee X.
This section presents the proposed solution.
The proposed solution consists in deploying the following components, in order:
Prism is an open-source HTTP mock server that can mimic your API’s behavior as if you already built it. Mock HTTP servers are generated from your OpenAPI v2/v3 (formerly known as Swagger) documents.
The main advantage of using prism is that you do not have to write any code to implement the mock APIs on Cloud Run.
In this section, we describe the different steps to deploy the solution.
In our example, we use the petstore OpenAPI Specification that is publicly available, but you can choose another document of your convenience.
We also consider that the following tools are set on the local machine used for the deployment:
The Apigee Sackmesser tool lets you deploy API proxies, shared flows and configuration to Apigee Edge as well as Apigee hybrid/X, without writing any additional manifest files.
In the coming sections, we use the following environment variables:
In the current directory, we create a specs sub directory in which we download the petstore.yaml file, using the following command:
mkdir ./specs
curl -L0 https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/examples/v3.0/petstore.yaml > ./specs/petstore.yaml
export OPEN_API_SPEC_MOCK=./specs/petstore.yaml
Let’s go on with the creation of the Dockerfile, based on the stoplight/prism (version 4) image:
cat > Dockerfile <<EOF
FROM stoplight/prism:4
ADD $OPEN_API_SPEC_MOCK /usr/src/prism/openapi.yaml
EXPOSE 4010
CMD ["mock","-d","-h","'0.0.0.0'","/usr/src/prism/openapi.yaml"]
EOF
docker build -t gcr.io/"$GCP_PROJECT"/apigee-mock-target:latest .
docker push gcr.io/"$GCP_PROJECT"/apigee-mock-target:latest
We use the prism mock command to start a server, which exposes the petstore API.
The -d option is used to generate dynamic random examples based on the API description, so the examples are always valid.
Once created, the Docker image is built and pushed to a container registry in your current GCP project. For a detail of the different possible options available with stoplight/prism, please refer to the online Stoplight Prism doc.
We can now deploy a Cloud Run service using the following command:
gcloud run deploy apigee-mock-target \
--image=gcr.io/"$GCP_PROJECT"/apigee-mock-target \
--platform=managed \
--port 4010 \
--region="$GCP_REGION" \
--no-allow-unauthenticated
TARGET_URL=$(gcloud run services describe apigee-mock-target --platform managed --region "$GCP_REGION" --format json | jq -r '.status.url')
We define the TARGET_URL variable that contains the value of the Cloud Run service’s target URL, once this service has been deployed. We use this variable to configure the target endpoint of the Apigee API proxy.
The Apigee API proxy (that is created later) needs a service account with the role “roles/run.invoker” as access to the Cloud Run service is authenticated.
gcloud iam service-accounts create oas-mock-target-sa \
--project "$GCP_PROJECT" || true
gcloud run services add-iam-policy-binding apigee-mock-target \
--region "$GCP_REGION" \
--member serviceAccount:oas-mock-target-sa@"$GCP_PROJECT".iam.gserviceaccount.com \
--role roles/run.invoker \
--platform managed
We use a simple pass-through API proxy. The only configuration aspect that requires your attention is the target endpoint.
Here is an example of the target endpoint configuration that you can use in order to use Google authentication to connect with the Cloud Run service that has been created before:
<TargetEndpoint name="default">
<HTTPTargetConnection>
<URL>@TargetURL@</URL>
<Authentication>
<GoogleIDToken>
<Audience>@TargetURL@</Audience>
</GoogleIDToken>
</Authentication>
</HTTPTargetConnection>
</TargetEndpoint>
You must now replace the @TargetURL@ tag with the value of the TARGET_URL variable, as shown with the following sed command:
sed -i.bak "s|@TargetURL@|$TARGET_URL|" ./api-proxy-v1/apiproxy/targets/default.xml
rm ./api-proxy-v1/apiproxy/targets/default.xml.bak
We consider here that the target endpoint configuration is contained in the default.xml file, that is part of the /api-proxy-v1/apiproxy/targets/ directory.
Here is an overview of the api-proxy-v1 directory structure:
api-proxy-v1/
└── apiproxy
├── apigee-v1.xml
├── policies
│ └── SpikeArrest.xml
├── proxies
│ └── default.xml
└── targets
└── default.xml
4 directories, 4 files
The only policy we have defined is a SpikeArrest policy to protect the mock service. This policy is not mandatory if you want to start with a (very) simple API proxy.
Now we can deploy the API proxy using the sackmesser command. In our example, the configuration of the API proxy that is deployed is defined in the api-proxy-v1 directory:
sackmesser deploy --googleapi \
-o "$APIGEE_X_ORG" \
-e "$APIGEE_X_ENV" \
-t "$APIGEE_TOKEN" \
-h "$APIGEE_X_HOSTNAME" \
-d "./api-proxy-v1" \
--deployment-sa oas-mock-target-sa@"$GCP_PROJECT".iam.gserviceaccount.com
The APIGEE_TOKEN environment variable is generated using the following gcloud command:
APIGEE_TOKEN=$(gcloud auth print-access-token)
The service account that is configured at the API proxy level and that is used to generate a valid access token to connect with the Cloud Run service is defined with the --deployment-sa option.
Once deployed, the solution can be tested using any HTTP client (here we are using curl):
curl https://"$APIGEE_X_HOSTNAME"/api/v1/pets | jq
The response is an array, including at least one pet in the form of:
{
"id": 5712447680535704000,
"name": "velit",
"tag": "ullamco minim"
}
The id, name and tag are dynamically generated by the stoplight/prism mocker.
The debug traces on Apigee (X or hybrid) provide the following information, like the mock service’s response:
Metrics related to the Cloud Run mock service can be retrieved from the GCP console:
In order to clean up what has been previously deployed, you can use the following commands:
rm -r ./api-proxy-v1
rm Dockerfile
# delete the API proxy proxy from Apigee X or hybrid
APIGEE_TOKEN=$(gcloud auth print-access-token);
sackmesser clean --googleapi -t "$APIGEE_TOKEN" proxy <API-PROXY-NAME>
# Cleanup GCP Assets
gcloud run services delete apigee-mock-target \
--region "$GCP_REGION" -q
gcloud iam service-accounts delete oas-mock-target-sa@"$GCP_PROJECT".iam.gserviceaccount.com \
--project "$GCP_PROJECT" -q
Thanks to Omid Tahouri and Daniel Strebel for their feedback on drafts of this article!