Just trying to understand pact. We are using spring boot, so naturally I went to trying simple setup using pact-jvm-provider-spring-mvc.
My pact file is a simple
{
"consumer": {
"name": "MyConsumer"
},
"provider": {
"name": "MyProvider"
},
"interactions": [
{
"description": "a request for projects",
"providerState": "i have a list of projects",
"request": {
"method": "GET",
"path": "/dogs",
"headers": {
"Accept": "application/json"
}
},
"response": {
"status": 200,
"headers": {
"Content-Type": "application/json"
},
"body": [
{
"dog": "1"
}
]
}
}
],
"metadata": {
"pactSpecification": {
"version": "2.0.0"
}
}
}
I added these dependencies to my gradle build:
```
testCompile group: 'com.reagroup', name: 'pact-jvm-provider-spring-mvc_2.10', version: '0.4.0'
testCompile group: 'au.com.dius', name: 'pact-jvm-provider_2.10', version: '2.4.18'
testCompile group: 'au.com.dius', name: 'pact-jvm-provider-junit_2.11', version: '3.4.1'
```
The test class doesn't do much, just creates a controller in spring fashion.
But what I get from running it is
```
org.json4s.package$MappingException: Case classes defined in function bodies are not supported.
at org.json4s.reflect.package$.fail(package.scala:96)
at org.json4s.reflect.Reflector$ClassDescriptorBuilder$$anonfun$9.apply(Reflector.scala:115)
at org.json4s.reflect.Reflector$ClassDescriptorBuilder$$anonfun$9.apply(Reflector.scala:115)
at scala.util.control.Exception$Catch$$anon$2.apply(Exception.scala:137)
at scala.util.control.Exception$Catch$$anon$2.apply(Exception.scala:135)
at scala.util.control.Exception$Catch.apply(Exception.scala:106)
at org.json4s.reflect.Reflector$ClassDescriptorBuilder.constructorsAndCompanion(Reflector.scala:115)
at org.json4s.reflect.Reflector$ClassDescriptorBuilder.result(Reflector.scala:156)
at org.json4s.reflect.Reflector$.createDescriptor(Reflector.scala:50)
at org.json4s.reflect.Reflector$$anonfun$describe$1.apply(Reflector.scala:44)
at org.json4s.reflect.Reflector$$anonfun$describe$1.apply(Reflector.scala:44)
at org.json4s.reflect.package$Memo.apply(package.scala:39)
at org.json4s.reflect.Reflector$.describe(Reflector.scala:44)
at org.json4s.Extraction$.extract(Extraction.scala:330)
```
It seems like a bug in the underlying jar file which is resolved. But I am just wondering if this is the right approach, can I simply bump the jar version for json4s?
The pact-jvm-provider-spring-mvc is not touched in a while, and the 0.5.0 version never released. Again note that I don't need spring-mvc. I just want to test Pact against my rest api.
I thought there might be another way of doing this.
Make sure the request body matches what the api expects.
I've gotten similar errors (but from jackson) when that was the case.
Related
I've installed apisix and apisix-dashboard with helm on my k8s cluster.
I used all defaults except APIKEY for admin and viewer acc., and custom username/password for dashboard. So I'm currently running the 2.15 version.
My installation steps
helm repo add apisix https://charts.apiseven.com
helm repo update
# installing apisix/apisix
helm install --set-string admin.credentials.admin="new_api_key"
--set-string admin.credentials.viewer="new_api_key" apisix apisix/apisix --create-namespace --namespace my-apisix
# installing apisix/apisix-dashboard, where values.yaml contains username/password
helm install -f values.yaml apisix-dashboard apisix/apisix-dashboard --create-namespace --namespace my-apisix
I'm unable to configure the mocking plugin, I've been following the docs.
In the provided example I'm unable to call the API on route with ID 1, so I've created a custom route and after that used the VIEW json, where I've changed the configuration accordingly to the sample provided.
All calls on this routes are returning 502 errors, in the logs i can see the route is routing traffic to a non existing server. All of that leads me to believe that the mocking plugin is disabled.
Example of my route:
{
"uri": "/mock-test.html",
"name": "mock-sample-read",
"methods": [
"GET"
],
"plugins": {
"mocking": {
"content_type": "application/json",
"delay": 1,
"disable": false,
"response_schema": {
"$schema": "http://json-schema.org/draft-04/schema#",
"properties": {
"a": {
"type": "integer"
},
"b": {
"type": "integer"
}
},
"required": [
"a",
"b"
],
"type": "object"
},
"response_status": 200,
"with_mock_header": true
}
},
"upstream": {
"nodes": [
{
"host": "127.0.0.1",
"port": 1980,
"weight": 1
}
],
"timeout": {
"connect": 6,
"send": 6,
"read": 6
},
"type": "roundrobin",
"scheme": "https",
"pass_host": "node",
"keepalive_pool": {
"idle_timeout": 60,
"requests": 1000,
"size": 320
}
},
"status": 1
}
Can anyone provide me with an actual working example or point out what I'm missing? Any suggestions are welcomed.
EDIT:
Looking at the logs of the apache/apisix:2.15.0-alpine it looks like this mocking plugin is disabled. Looking at the docs The mocking Plugin is used for mocking an API. When executed, it returns random mock data in the format specified and the request is not forwarded to the Upstream.
Error logs where I've changed the domain and IP addr. suggest that the traffic is being redirected to the upstream:
10.10.10.24 - - [23/Sep/2022:11:33:16 +0000] my.domain.com "GET /mock-test.html HTTP/1.1" 502 154 0.001 "-" "PostmanRuntime/7.29.2" 127.0.0.1:1980 502 0.001 "http://my.domain.com"
Globally plugins are enabled, I've tested using the Keycloak plugin.
EDIT 2: Could this be a bug in version 2.15 of apisix? There is currently no open issue on the github repo.
yes, mocking plugin is not enabled.
you can just add it here.
https://github.com/apache/apisix-helm-chart/blob/7ddeca5395a2de96acd06bada30f3ab3580a6252/charts/apisix/values.yaml#L219-L269
You can also submit a PR directly to fix it
So I've run into this issue with a web app I've made:
it gets a file path as input
if the file exists on a bucket, it uses a python client api to create a compute engine instance
it passes the file path to the instance in the startup script
When I ran it locally, I created a python virtual environment and then ran the app. When I make the input on the web browser, the virtual machine is created by the api call. I assumed it used my personal account. I changed to the service account in the command line with this command 'gcloud config set account', it ran fine once more.
When I simply go to the source code directory deploy it as is, the application can create the virtual machine instances as well.
When I use Google cloud build and deploy to cloud run, it doesn't create the vm instance.
the web app itself is not throwing any errors, but when I check compute engine's logs, there is an error in the logs:
`{
"protoPayload": {
"#type": "type.googleapis.com/google.cloud.audit.AuditLog",
"status": {
"code": 3,
"message": "INVALID_PARAMETER"
},
"authenticationInfo": {
"principalEmail": "####"
},
"requestMetadata": {
"callerIp": "#####",
"callerSuppliedUserAgent": "(gzip),gzip(gfe)"
},
"serviceName": "compute.googleapis.com",
"methodName": "v1.compute.instances.insert",
"resourceName": "projects/someproject/zones/somezone/instances/nameofinstance",
"request": {
"#type": "type.googleapis.com/compute.instances.insert"
}
},
"insertId": "######",
"resource": {
"type": "gce_instance",
"labels": {
"instance_id": "#####",
"project_id": "someproject",
"zone": "somezone"
}
},
"timestamp": "2021-06-16T12:18:21.253551Z",
"severity": "ERROR",
"logName": "projects/someproject/logs/cloudaudit.googleapis.com%2Factivity",
"operation": {
"id": "operation-#####",
"producer": "compute.googleapis.com",
"last": true
},
"receiveTimestamp": "2021-06-16T12:18:21.253551Z"
}`
In theory, it is the same exact code that worked from my laptop and on app engine. I'm baffled why it only does this for cloud run.
App engines default service account was stripped of all its roles and given a custom role tailored to the web apps function.
The cloud run is using a different service account, but was given that exact same custom role.
Here is the method I use to call the api.
def create_instance(path):
compute = googleapiclient.discovery.build('compute', 'v1')
vmname = "piinnuclei" + date.today().strftime("%Y%m%d%H%M%S")
startup_script = "#! /bin/bash\napt update\npip3 install pg8000\nexport BUCKET_PATH=my-bucket/{}\ngsutil -m cp -r gs://$BUCKET_PATH /home/connor\ncd /home/connor\n./cloud_sql_proxy -dir=cloudsql -instances=sql-connection-name=unix:sql-connection-name &\npython3 run_analysis_upload.py\nexport ZONE=$(curl -X GET http://metadata.google.internal/computeMetadata/v1/instance/zone -H 'Metadata-Flavor: Google')\nexport NAME=$(curl -X GET http://metadata.google.internal/computeMetadata/v1/instance/name -H 'Metadata-Flavor: Google')\ngcloud --quiet compute instances delete $NAME --zone=$ZONE".format(path)
config = {
"kind": "compute#instance",
"name": vmname,
"zone": "projects/my-project/zones/northamerica-northeast1-a",
"machineType": "projects/my-project/zones/northamerica-northeast1-a/machineTypes/e2-standard-4",
"displayDevice": {
"enableDisplay": False
},
"metadata": {
"kind": "compute#metadata",
"items": [
{
"key": "startup-script",
"value": startup_script
}
]
},
"tags": {
"items": []
},
"disks": [
{
"kind": "compute#attachedDisk",
"type": "PERSISTENT",
"boot": True,
"mode": "READ_WRITE",
"autoDelete": True,
"deviceName": vmname,
"initializeParams": {
"sourceImage": "projects/my-project/global/images/my-image",
"diskType": "projects/my-project/zones/northamerica-northeast1-a/diskTypes/pd-balanced",
"diskSizeGb": "100"
},
"diskEncryptionKey": {}
}
],
"canIpForward": False,
"networkInterfaces": [
{
"kind": "compute#networkInterface",
"subnetwork": "projects/my-project/regions/northamerica-northeast1/subnetworks/default",
"accessConfigs": [
{
"kind": "compute#accessConfig",
"name": "External NAT",
"type": "ONE_TO_ONE_NAT",
"networkTier": "PREMIUM"
}
],
"aliasIpRanges": []
}
],
"description": "",
"labels": {},
"scheduling": {
"preemptible": False,
"onHostMaintenance": "MIGRATE",
"automaticRestart": True,
"nodeAffinities": []
},
"deletionProtection": False,
"reservationAffinity": {
"consumeReservationType": "ANY_RESERVATION"
},
"serviceAccounts": [
{
"email": "batch-service-accountg#my-project.iam.gserviceaccount.com",
"scopes": [
"https://www.googleapis.com/auth/cloud-platform"
]
}
],
"shieldedInstanceConfig": {
"enableSecureBoot": False,
"enableVtpm": True,
"enableIntegrityMonitoring": True
},
"confidentialInstanceConfig": {
"enableConfidentialCompute": False
}
}
return compute.instances().insert(
project="my-project",
zone="northamerica-northeast1",
body=config).execute()
The issue was with the zone. For some reason, when it was ran on cloud run, the code below was the culprit.
return compute.instances().insert(
project="my-project",
zone="northamerica-northeast1",
body=config).execute()
"northamerica-northeast1" should have been "northamerica-northeast1-a"
EDIT:
I made a new virtual machine image and quickly ran into the same problem, it would work locally and break down in the cloud run environment. After letting it sit for some time, it began to work again. This is leading me to the conclusion that there is also some sort of delay before it can be called by cloud run.
I am trying to make http://json-schema.org/draft-04/schema# to be in local repository.
But it is unable to find the referred JSON in any of the path, be it root, resources or current directly or inside the jar.
As these are run-time exception, it seems the json-schema.org/draft-04/schema.json file in resource as well with the jar is not in the pakaged build.
Is there a way, I can define in JavaCompile in build.gradle to pick the json files
Below are the code snippet
Schema.json:
{
"$ref": "file://json-schema-draft-04-schema.json",
"type": "object",
"title": "Hyperledger Fabric Contract Definition JSON Schema",
"required": [
"info",
"contracts"
],
"properties": {
"info": {
"$ref": "#/definitions/info"
},
"contracts": {
"type": "object",
"patternProperties": {
"^.*$": {
"$ref": "#/definitions/contract"
}
}
},
"components": {
"$ref": "#/definitions/components"
}
},
"definitions": {
"info": {
"type": "object",
"description": "General information about the API.",
"required": [
"version",
"title"
],
"properties": {
"title": {
"type": "string",
"description": "A unique and precise title of the API."
},
"version": {
"type": "string",
"description": "A semantic version number of the API."
},
"description": {
"type": "string",
"description": "A longer description of the API. Should be different from the title. GitHub Flavored Markdown is allowed."
},
"termsOfService": {
"type": "string",
"description": "The terms of service for the API."
},
"contact": {
"$ref": "#/definitions/contact"
},
"license": {
"$ref": "#/definitions/license"
}
}
},
Referred to json json-schema-draft-04-schema.json:
{
"id": "http://json-schema.org/draft-04/schema#",
"description": "Core schema meta-schema",
"definitions": {
"schemaArray": {
"type": "array",
"minItems": 1,
"items": { "$ref": "#" }
},
"positiveInteger": {
"type": "integer",
"minimum": 0
},
"positiveIntegerDefault0": {
"allOf": [ { "$ref": "#/definitions/positiveInteger" }, { "default": 0 } ]
},
"simpleTypes": {
"enum": [ "array", "boolean", "integer", "null", "number", "object", "string" ]
},
"stringArray": {
"type": "array",
"items": { "type": "string" },
"minItems": 1,
"uniqueItems": true
}
},
"type": "object",
"properties": {
"id": {
"type": "string"
},
"$schema": {
Error Quote
0|Exception in thread "main" java.io.UncheckedIOException: java.io.FileNotFoundException: /json-schema-draft-04-schema.json (No such file or directory)
dev-peer0.org1.example.com-papercontract-0| at org.everit.json.schema.loader.internal.DefaultSchemaClient.get(DefaultSchemaClient.java:20)
dev-peer0.org1.example.com-papercontract-0| at org.everit.json.schema.loader.JsonPointerEvaluator.executeWith(JsonPointerEvaluator.java:78)
dev-peer0.org1.example.com-papercontract-0| at org.everit.json.schema.loader.JsonPointerEvaluator.lambda$forURL$1(JsonPointerEvaluator.java:121)
dev-peer0.org1.example.com-papercontract-0| at org.everit.json.schema.loader.JsonPointerEvaluator.query(JsonPointerEvaluator.java:151)
dev-peer0.org1.example.com-papercontract-0| at org.everit.json.schema.loader.ReferenceLookup.lookup(ReferenceLookup.java:173)
dev-peer0.org1.example.com-papercontract-0| at org.everit.json.schema.loader.ReferenceSchemaExtractor.extract(SchemaExtractor.java:193)
dev-peer0.org1.example.com-papercontract-0| at org.everit.json.schema.loader.AbstractSchemaExtractor.extract(SchemaExtractor.java:113)
dev-peer0.org1.example.com-papercontract-0| at org.everit.json.schema.loader.SchemaLoader.runSchemaExtractors(SchemaLoader.java:383)
dev-peer0.org1.example.com-papercontract-0| at org.everit.json.schema.loader.SchemaLoader.loadSchemaObject(SchemaLoader.java:360)
dev-peer0.org1.example.com-papercontract-0| at org.everit.json.schema.loader.JsonValue$Multiplexer.requireAny(JsonValue.java:46)
dev-peer0.org1.example.com-papercontract-0| at org.everit.json.schema.loader.SchemaLoader.load(SchemaLoader.java:434)
dev-peer0.org1.example.com-papercontract-0| at org.hyperledger.fabric.contract.metadata.MetadataBuilder.validate(MetadataBuilder.java:87)
dev-peer0.org1.example.com-papercontract-0| at org.hyperledger.fabric.contract.metadata.MetadataBuilder.initialize(MetadataBuilder.java:115)
dev-peer0.org1.example.com-papercontract-0| at org.hyperledger.fabric.contract.ContractRouter.main(ContractRouter.java:134)
dev-peer0.org1.example.com-papercontract-0|Caused by: java.io.FileNotFoundException: /json-schema-draft-04-schema.json (No such file or directory)
dev-peer0.org1.example.com-papercontract-0| at java.io.FileInputStream.open0(Native Method)
dev-peer0.org1.example.com-papercontract-0| at java.io.FileInputStream.open(FileInputStream.java:195)
dev-peer0.org1.example.com-papercontract-0| at java.io.FileInputStream.<init>(FileInputStream.java:138)
dev-peer0.org1.example.com-papercontract-0| at java.io.FileInputStream.<init>(FileInputStream.java:93)
dev-peer0.org1.example.com-papercontract-0| at sun.net.www.protocol.file.FileURLConnection.connect(FileURLConnection.java:90)
dev-peer0.org1.example.com-papercontract-0| at sun.net.www.protocol.file.FileURLConnection.getInputStream(FileURLConnection.java:188)
dev-peer0.org1.example.com-papercontract-0| at java.net.URLConnection.getContent(URLConnection.java:739)
dev-peer0.org1.example.com-papercontract-0| at java.net.URL.getContent(URL.java:1059)
dev-peer0.org1.example.com-papercontract-0| at org.everit.json.schema.loader.internal.DefaultSchemaClient.get(DefaultSchemaClient.java:18)
dev-peer0.org1.example.com-papercontract-0| ... 13 more
build.gradle
plugins {
id 'java'
//id 'application'
id 'com.github.johnrengelman.shadow' version '2.0.3'
}
version '0.0.1'
sourceCompatibility = 1.8
repositories {
// flatDir { dirs 'libs' }
mavenLocal()
maven {
url 'http://repo1.maven.org/maven2'
}
maven {
url 'https://jitpack.io'
}
maven {
url "https://nexus.hyperledger.org/content/repositories/snapshots/"
}
}
dependencies {
//compile group: 'org.hyperledger.fabric-chaincode-java', name: 'fabric-chaincode-shim',version: '1.4.3'
compile fileTree(dir: 'libs', include: '*.jar') // local fabric-chaincode-shim which has json
// schema locally store in the jar. Also, there is one in resources folder.
compile group: 'org.hyperledger.fabric-sdk-java', name: 'fabric-sdk-java', version: '1.4.4'
compile 'org.reflections:reflections:0.9.11'
implementation 'com.github.everit-org.json-schema:org.everit.json.schema:1.11.1'
compile 'io.swagger.core.v3:swagger-annotations:2.0.0'
compile group: 'org.json', name: 'json', version: '20180813'
testImplementation 'org.junit.jupiter:junit-jupiter:5.4.2'
testImplementation 'org.assertj:assertj-core:3.11.1'
testImplementation 'org.mockito:mockito-core:2.+'
}
shadowJar {
baseName = 'chaincode'
version = null
classifier = null
manifest {
attributes 'Main-Class': 'org.hyperledger.fabric.contract.ContractRouter'
}
}
test {
useJUnitPlatform()
testLogging {
events "passed", "skipped", "failed"
}
}
tasks.withType(JavaCompile) {
options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation" << "-parameters"
}
Both the file are inside an executable jar.
I tried putting the reference .json file in root of the project as well, but no luck.
Tried using classpath:// as well.
No luck.
There are two possible issues here.
First, you are assuming the library you are using supports the file:// protocol. Is it specifically documented that you can references local files this way in the library you are using? JSON Schema itself makes no assumptions about protocol support, and does not know about itself as a file in a folder structure.
Second, you cannot use $ref alongside other keywords in the same object. Even if your reference did resolve, it would make all the other keywords in the schema ignored. You need to wrap it using an allOf.
I am trying to create a spec file for the go implementation of petstore example . I tried a go generate in the directory which had doc.go but it did nothing. On further reading, I realised that there should be
//go:generate swagger generate spec -o swagger.json
in doc.go . When I added that it creates a spec file but it doesn't contain the entire specification. This is the .json file that is create on go generate
{
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"schemes": [
"http",
"https"
],
"swagger": "2.0",
"info": {
"description": "the purpose of this application is to provide an application\nthat is using plain go code to define an API\n\nThis should demonstrate all the possible comment annotations\nthat are available to turn go code into a fully compliant swagger 2.0 spec",
"title": "Petstore API.",
"termsOfService": "there are no TOS at this moment, use at your own risk we take no responsibility\ngo:generate swagger generate spec -o swagger.json",
"contact": {
"name": "John Doe",
"url": "http://john.doe.com",
"email": "john.doe#example.com"
},
"license": {
"name": "MIT",
"url": "http://opensource.org/licenses/MIT"
},
"version": "0.0.1"
},
"host": "localhost",
"basePath": "/v2",
"paths": {}
}
There are no routes/parameters/models mentioned in the spec file. Is this how this is supposed to be? This is an official example from the goswagger repo so I doubt the code is wrong. What should I change to make it work?
The code you want to document needs to be reachable from your main package. That means from the main package its usage needs to be detectable.
So if you have a working server that isn't hooked up through some means of reflection it will generate the right specification.
I created an empty asp.net web application project with rc2. My project file is:
{
"testRunner": "xunit",
"dependencies": {
"xunit": "2.1.0",
"dotnet-test-xunit": "1.0.0-rc2-build10025",
"Microsoft.NETCore.App": {
"version": "1.0.0-rc2-3002702",
"type": "platform"
},
"Microsoft.AspNetCore.Server.IISIntegration": "1.0.0-rc2-final",
"Microsoft.AspNetCore.Server.Kestrel": "1.0.0-rc2-final",
"Microsoft.AspNetCore.Mvc.Cors": "1.0.0-rc2-final",
"Microsoft.AspNetCore.Mvc.ViewFeatures": "1.0.0-rc2-final"
},
"tools": {
"Microsoft.AspNetCore.Server.IISIntegration.Tools": {
"version": "1.0.0-preview1-final",
"imports": "portable-net45+win8+dnxcore50"
}
},
"frameworks": {
"netcoreapp1.0": {
"imports": [
"dotnet5.6",
"dnxcore50",
"portable-net45+win8"
]
}
},
"buildOptions": {
"emitEntryPoint": true,
"preserveCompilationContext": true
},
"runtimeOptions": {
"gcServer": true
},
"publishOptions": {
"include": [
"wwwroot",
"web.config"
]
},
"scripts": {
"postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ]
}
}
Now I want to add HttpConfiguration config = new HttpConfiguration(); in my unit test.
But HtppConfiguration is from ASP.NET WEB API 2. How to change my project.json file? Or is there any replacement for it in ASP.NET CORE RC2?
ASP.Core provides an easy way for integration testing using TestServer class. The following may help to start using it:
an ASP.Net Core documentation about integration testing.
a post about using TestServer with example on github.
a TestServerTests.cs file from Hosting repo, that contains xunit tests for TestServer. May help to review, what TestServer can do.
good question on SO: "Why the TestServer (AspNetCore) gives 404 error on static files?"
and keep in mind that a lot of projects in https://github.com/aspnet use TestServer for testing (like Diagnostics ).