From 88fe9343499be08d4e9e1f0379a7babff90febee Mon Sep 17 00:00:00 2001 From: ianroydemo <96147516+ianroydemo@users.noreply.github.com> Date: Fri, 28 Jan 2022 11:45:00 -0500 Subject: [PATCH 01/19] Update README.md --- catalog-service/README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/catalog-service/README.md b/catalog-service/README.md index 1855f385..4a2a3eca 100644 --- a/catalog-service/README.md +++ b/catalog-service/README.md @@ -1,3 +1,12 @@ + +[![Overall](https://img.shields.io/endpoint?style=flat&url=https%3A%2F%2Fapp.opslevel.com%2Fapi%2Fservice_level%2Fh4dYSGsAWr2B_kbSt0qB-AVP2uqsG7Dqs-fPUkPYnuk)](https://app.opslevel.com/services/catalog_service/maturity-report) +[![All Checks available](https://img.shields.io/endpoint?style=flat&url=https%3A%2F%2Fapp.opslevel.com%2Fapi%2Fservice_level%2Fh4dYSGsAWr2B_kbSt0qB-AVP2uqsG7Dqs-fPUkPYnuk%2Fall_checks_available)](https://app.opslevel.com/services/catalog_service/maturity-report) +[![Service Ownership](https://img.shields.io/endpoint?style=flat&url=https%3A%2F%2Fapp.opslevel.com%2Fapi%2Fservice_level%2Fh4dYSGsAWr2B_kbSt0qB-AVP2uqsG7Dqs-fPUkPYnuk%2Fservice_ownership)](https://app.opslevel.com/services/catalog_service/maturity-report) +[![Security](https://img.shields.io/endpoint?style=flat&url=https%3A%2F%2Fapp.opslevel.com%2Fapi%2Fservice_level%2Fh4dYSGsAWr2B_kbSt0qB-AVP2uqsG7Dqs-fPUkPYnuk%2Fsecurity_2)](https://app.opslevel.com/services/catalog_service/maturity-report) +[![Reliability](https://img.shields.io/endpoint?style=flat&url=https%3A%2F%2Fapp.opslevel.com%2Fapi%2Fservice_level%2Fh4dYSGsAWr2B_kbSt0qB-AVP2uqsG7Dqs-fPUkPYnuk%2Freliability_2)](https://app.opslevel.com/services/catalog_service/maturity-report) +[![Scalability](https://img.shields.io/endpoint?style=flat&url=https%3A%2F%2Fapp.opslevel.com%2Fapi%2Fservice_level%2Fh4dYSGsAWr2B_kbSt0qB-AVP2uqsG7Dqs-fPUkPYnuk%2Fscalability_2)](https://app.opslevel.com/services/catalog_service/maturity-report) +[![Observability](https://img.shields.io/endpoint?style=flat&url=https%3A%2F%2Fapp.opslevel.com%2Fapi%2Fservice_level%2Fh4dYSGsAWr2B_kbSt0qB-AVP2uqsG7Dqs-fPUkPYnuk%2Fobservability_2)](https://app.opslevel.com/services/catalog_service/maturity-report) +[![Quality](https://img.shields.io/endpoint?style=flat&url=https%3A%2F%2Fapp.opslevel.com%2Fapi%2Fservice_level%2Fh4dYSGsAWr2B_kbSt0qB-AVP2uqsG7Dqs-fPUkPYnuk%2Fquality_2)](https://app.opslevel.com/services/catalog_service/maturity-report) This sample contains [sbt](http://www.scala-sbt.org/) build settings and test classes for illustrating multi-node testing with Akka. Please refer to the full documentation of [multi-node testing](http://doc.akka.io/docs/akka/2.5/dev/multi-node-testing.html) and the closely related [multi-jvm testing](http://doc.akka.io/docs/akka/2.5/dev/multi-jvm-testing.html) for details. There is also an section on [cluster testing](http://doc.akka.io/docs/akka/2.5/scala/cluster-usage.html#How_to_Test). From d7d4617f7c2b82d725ff26207e03f85712f146d6 Mon Sep 17 00:00:00 2001 From: GandalfsBooks <96147516+ianroydemo@users.noreply.github.com> Date: Thu, 21 Apr 2022 16:23:53 -0400 Subject: [PATCH 02/19] Update README.md --- catalog-service/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/catalog-service/README.md b/catalog-service/README.md index 4a2a3eca..cd60f6fd 100644 --- a/catalog-service/README.md +++ b/catalog-service/README.md @@ -1,6 +1,5 @@ [![Overall](https://img.shields.io/endpoint?style=flat&url=https%3A%2F%2Fapp.opslevel.com%2Fapi%2Fservice_level%2Fh4dYSGsAWr2B_kbSt0qB-AVP2uqsG7Dqs-fPUkPYnuk)](https://app.opslevel.com/services/catalog_service/maturity-report) -[![All Checks available](https://img.shields.io/endpoint?style=flat&url=https%3A%2F%2Fapp.opslevel.com%2Fapi%2Fservice_level%2Fh4dYSGsAWr2B_kbSt0qB-AVP2uqsG7Dqs-fPUkPYnuk%2Fall_checks_available)](https://app.opslevel.com/services/catalog_service/maturity-report) [![Service Ownership](https://img.shields.io/endpoint?style=flat&url=https%3A%2F%2Fapp.opslevel.com%2Fapi%2Fservice_level%2Fh4dYSGsAWr2B_kbSt0qB-AVP2uqsG7Dqs-fPUkPYnuk%2Fservice_ownership)](https://app.opslevel.com/services/catalog_service/maturity-report) [![Security](https://img.shields.io/endpoint?style=flat&url=https%3A%2F%2Fapp.opslevel.com%2Fapi%2Fservice_level%2Fh4dYSGsAWr2B_kbSt0qB-AVP2uqsG7Dqs-fPUkPYnuk%2Fsecurity_2)](https://app.opslevel.com/services/catalog_service/maturity-report) [![Reliability](https://img.shields.io/endpoint?style=flat&url=https%3A%2F%2Fapp.opslevel.com%2Fapi%2Fservice_level%2Fh4dYSGsAWr2B_kbSt0qB-AVP2uqsG7Dqs-fPUkPYnuk%2Freliability_2)](https://app.opslevel.com/services/catalog_service/maturity-report) From 45bcd351140779cb4fb98599aae45a92f55d7f66 Mon Sep 17 00:00:00 2001 From: GandalfsBooks <96147516+ianroydemo@users.noreply.github.com> Date: Thu, 21 Apr 2022 16:24:05 -0400 Subject: [PATCH 03/19] Update README.md --- catalog-service/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/catalog-service/README.md b/catalog-service/README.md index cd60f6fd..ccb810ed 100644 --- a/catalog-service/README.md +++ b/catalog-service/README.md @@ -6,6 +6,7 @@ [![Scalability](https://img.shields.io/endpoint?style=flat&url=https%3A%2F%2Fapp.opslevel.com%2Fapi%2Fservice_level%2Fh4dYSGsAWr2B_kbSt0qB-AVP2uqsG7Dqs-fPUkPYnuk%2Fscalability_2)](https://app.opslevel.com/services/catalog_service/maturity-report) [![Observability](https://img.shields.io/endpoint?style=flat&url=https%3A%2F%2Fapp.opslevel.com%2Fapi%2Fservice_level%2Fh4dYSGsAWr2B_kbSt0qB-AVP2uqsG7Dqs-fPUkPYnuk%2Fobservability_2)](https://app.opslevel.com/services/catalog_service/maturity-report) [![Quality](https://img.shields.io/endpoint?style=flat&url=https%3A%2F%2Fapp.opslevel.com%2Fapi%2Fservice_level%2Fh4dYSGsAWr2B_kbSt0qB-AVP2uqsG7Dqs-fPUkPYnuk%2Fquality_2)](https://app.opslevel.com/services/catalog_service/maturity-report) + This sample contains [sbt](http://www.scala-sbt.org/) build settings and test classes for illustrating multi-node testing with Akka. Please refer to the full documentation of [multi-node testing](http://doc.akka.io/docs/akka/2.5/dev/multi-node-testing.html) and the closely related [multi-jvm testing](http://doc.akka.io/docs/akka/2.5/dev/multi-jvm-testing.html) for details. There is also an section on [cluster testing](http://doc.akka.io/docs/akka/2.5/scala/cluster-usage.html#How_to_Test). From dfd3bc82eab901e19b21c805e2ad4c267c3781b9 Mon Sep 17 00:00:00 2001 From: GandalfsBooks <96147516+ianroydemo@users.noreply.github.com> Date: Thu, 21 Apr 2022 16:25:01 -0400 Subject: [PATCH 04/19] Add files via upload --- catalog-service/swagger.json | 1 + 1 file changed, 1 insertion(+) create mode 100644 catalog-service/swagger.json diff --git a/catalog-service/swagger.json b/catalog-service/swagger.json new file mode 100644 index 00000000..84f510c1 --- /dev/null +++ b/catalog-service/swagger.json @@ -0,0 +1 @@ +{"swagger":"2.0","info":{"description":"This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters.","version":"1.0.6","title":"Swagger Petstore","termsOfService":"http://swagger.io/terms/","contact":{"email":"apiteam@swagger.io"},"license":{"name":"Apache 2.0","url":"http://www.apache.org/licenses/LICENSE-2.0.html"}},"host":"petstore.swagger.io","basePath":"/v2","tags":[{"name":"pet","description":"Everything about your Pets","externalDocs":{"description":"Find out more","url":"http://swagger.io"}},{"name":"store","description":"Access to Petstore orders"},{"name":"user","description":"Operations about user","externalDocs":{"description":"Find out more about our store","url":"http://swagger.io"}}],"schemes":["https","http"],"paths":{"/pet/{petId}/uploadImage":{"post":{"tags":["pet"],"summary":"uploads an image","description":"","operationId":"uploadFile","consumes":["multipart/form-data"],"produces":["application/json"],"parameters":[{"name":"petId","in":"path","description":"ID of pet to update","required":true,"type":"integer","format":"int64"},{"name":"additionalMetadata","in":"formData","description":"Additional data to pass to server","required":false,"type":"string"},{"name":"file","in":"formData","description":"file to upload","required":false,"type":"file"}],"responses":{"200":{"description":"successful operation","schema":{"$ref":"#/definitions/ApiResponse"}}},"security":[{"petstore_auth":["write:pets","read:pets"]}]}},"/pet":{"post":{"tags":["pet"],"summary":"Add a new pet to the store","description":"","operationId":"addPet","consumes":["application/json","application/xml"],"produces":["application/json","application/xml"],"parameters":[{"in":"body","name":"body","description":"Pet object that needs to be added to the store","required":true,"schema":{"$ref":"#/definitions/Pet"}}],"responses":{"405":{"description":"Invalid input"}},"security":[{"petstore_auth":["write:pets","read:pets"]}]},"put":{"tags":["pet"],"summary":"Update an existing pet","description":"","operationId":"updatePet","consumes":["application/json","application/xml"],"produces":["application/json","application/xml"],"parameters":[{"in":"body","name":"body","description":"Pet object that needs to be added to the store","required":true,"schema":{"$ref":"#/definitions/Pet"}}],"responses":{"400":{"description":"Invalid ID supplied"},"404":{"description":"Pet not found"},"405":{"description":"Validation exception"}},"security":[{"petstore_auth":["write:pets","read:pets"]}]}},"/pet/findByStatus":{"get":{"tags":["pet"],"summary":"Finds Pets by status","description":"Multiple status values can be provided with comma separated strings","operationId":"findPetsByStatus","produces":["application/json","application/xml"],"parameters":[{"name":"status","in":"query","description":"Status values that need to be considered for filter","required":true,"type":"array","items":{"type":"string","enum":["available","pending","sold"],"default":"available"},"collectionFormat":"multi"}],"responses":{"200":{"description":"successful operation","schema":{"type":"array","items":{"$ref":"#/definitions/Pet"}}},"400":{"description":"Invalid status value"}},"security":[{"petstore_auth":["write:pets","read:pets"]}]}},"/pet/findByTags":{"get":{"tags":["pet"],"summary":"Finds Pets by tags","description":"Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.","operationId":"findPetsByTags","produces":["application/json","application/xml"],"parameters":[{"name":"tags","in":"query","description":"Tags to filter by","required":true,"type":"array","items":{"type":"string"},"collectionFormat":"multi"}],"responses":{"200":{"description":"successful operation","schema":{"type":"array","items":{"$ref":"#/definitions/Pet"}}},"400":{"description":"Invalid tag value"}},"security":[{"petstore_auth":["write:pets","read:pets"]}],"deprecated":true}},"/pet/{petId}":{"get":{"tags":["pet"],"summary":"Find pet by ID","description":"Returns a single pet","operationId":"getPetById","produces":["application/json","application/xml"],"parameters":[{"name":"petId","in":"path","description":"ID of pet to return","required":true,"type":"integer","format":"int64"}],"responses":{"200":{"description":"successful operation","schema":{"$ref":"#/definitions/Pet"}},"400":{"description":"Invalid ID supplied"},"404":{"description":"Pet not found"}},"security":[{"api_key":[]}]},"post":{"tags":["pet"],"summary":"Updates a pet in the store with form data","description":"","operationId":"updatePetWithForm","consumes":["application/x-www-form-urlencoded"],"produces":["application/json","application/xml"],"parameters":[{"name":"petId","in":"path","description":"ID of pet that needs to be updated","required":true,"type":"integer","format":"int64"},{"name":"name","in":"formData","description":"Updated name of the pet","required":false,"type":"string"},{"name":"status","in":"formData","description":"Updated status of the pet","required":false,"type":"string"}],"responses":{"405":{"description":"Invalid input"}},"security":[{"petstore_auth":["write:pets","read:pets"]}]},"delete":{"tags":["pet"],"summary":"Deletes a pet","description":"","operationId":"deletePet","produces":["application/json","application/xml"],"parameters":[{"name":"api_key","in":"header","required":false,"type":"string"},{"name":"petId","in":"path","description":"Pet id to delete","required":true,"type":"integer","format":"int64"}],"responses":{"400":{"description":"Invalid ID supplied"},"404":{"description":"Pet not found"}},"security":[{"petstore_auth":["write:pets","read:pets"]}]}},"/store/order":{"post":{"tags":["store"],"summary":"Place an order for a pet","description":"","operationId":"placeOrder","consumes":["application/json"],"produces":["application/json","application/xml"],"parameters":[{"in":"body","name":"body","description":"order placed for purchasing the pet","required":true,"schema":{"$ref":"#/definitions/Order"}}],"responses":{"200":{"description":"successful operation","schema":{"$ref":"#/definitions/Order"}},"400":{"description":"Invalid Order"}}}},"/store/order/{orderId}":{"get":{"tags":["store"],"summary":"Find purchase order by ID","description":"For valid response try integer IDs with value >= 1 and <= 10. Other values will generated exceptions","operationId":"getOrderById","produces":["application/json","application/xml"],"parameters":[{"name":"orderId","in":"path","description":"ID of pet that needs to be fetched","required":true,"type":"integer","maximum":10,"minimum":1,"format":"int64"}],"responses":{"200":{"description":"successful operation","schema":{"$ref":"#/definitions/Order"}},"400":{"description":"Invalid ID supplied"},"404":{"description":"Order not found"}}},"delete":{"tags":["store"],"summary":"Delete purchase order by ID","description":"For valid response try integer IDs with positive integer value. Negative or non-integer values will generate API errors","operationId":"deleteOrder","produces":["application/json","application/xml"],"parameters":[{"name":"orderId","in":"path","description":"ID of the order that needs to be deleted","required":true,"type":"integer","minimum":1,"format":"int64"}],"responses":{"400":{"description":"Invalid ID supplied"},"404":{"description":"Order not found"}}}},"/store/inventory":{"get":{"tags":["store"],"summary":"Returns pet inventories by status","description":"Returns a map of status codes to quantities","operationId":"getInventory","produces":["application/json"],"parameters":[],"responses":{"200":{"description":"successful operation","schema":{"type":"object","additionalProperties":{"type":"integer","format":"int32"}}}},"security":[{"api_key":[]}]}},"/user/createWithArray":{"post":{"tags":["user"],"summary":"Creates list of users with given input array","description":"","operationId":"createUsersWithArrayInput","consumes":["application/json"],"produces":["application/json","application/xml"],"parameters":[{"in":"body","name":"body","description":"List of user object","required":true,"schema":{"type":"array","items":{"$ref":"#/definitions/User"}}}],"responses":{"default":{"description":"successful operation"}}}},"/user/createWithList":{"post":{"tags":["user"],"summary":"Creates list of users with given input array","description":"","operationId":"createUsersWithListInput","consumes":["application/json"],"produces":["application/json","application/xml"],"parameters":[{"in":"body","name":"body","description":"List of user object","required":true,"schema":{"type":"array","items":{"$ref":"#/definitions/User"}}}],"responses":{"default":{"description":"successful operation"}}}},"/user/{username}":{"get":{"tags":["user"],"summary":"Get user by user name","description":"","operationId":"getUserByName","produces":["application/json","application/xml"],"parameters":[{"name":"username","in":"path","description":"The name that needs to be fetched. Use user1 for testing. ","required":true,"type":"string"}],"responses":{"200":{"description":"successful operation","schema":{"$ref":"#/definitions/User"}},"400":{"description":"Invalid username supplied"},"404":{"description":"User not found"}}},"put":{"tags":["user"],"summary":"Updated user","description":"This can only be done by the logged in user.","operationId":"updateUser","consumes":["application/json"],"produces":["application/json","application/xml"],"parameters":[{"name":"username","in":"path","description":"name that need to be updated","required":true,"type":"string"},{"in":"body","name":"body","description":"Updated user object","required":true,"schema":{"$ref":"#/definitions/User"}}],"responses":{"400":{"description":"Invalid user supplied"},"404":{"description":"User not found"}}},"delete":{"tags":["user"],"summary":"Delete user","description":"This can only be done by the logged in user.","operationId":"deleteUser","produces":["application/json","application/xml"],"parameters":[{"name":"username","in":"path","description":"The name that needs to be deleted","required":true,"type":"string"}],"responses":{"400":{"description":"Invalid username supplied"},"404":{"description":"User not found"}}}},"/user/login":{"get":{"tags":["user"],"summary":"Logs user into the system","description":"","operationId":"loginUser","produces":["application/json","application/xml"],"parameters":[{"name":"username","in":"query","description":"The user name for login","required":true,"type":"string"},{"name":"password","in":"query","description":"The password for login in clear text","required":true,"type":"string"}],"responses":{"200":{"description":"successful operation","headers":{"X-Expires-After":{"type":"string","format":"date-time","description":"date in UTC when token expires"},"X-Rate-Limit":{"type":"integer","format":"int32","description":"calls per hour allowed by the user"}},"schema":{"type":"string"}},"400":{"description":"Invalid username/password supplied"}}}},"/user/logout":{"get":{"tags":["user"],"summary":"Logs out current logged in user session","description":"","operationId":"logoutUser","produces":["application/json","application/xml"],"parameters":[],"responses":{"default":{"description":"successful operation"}}}},"/user":{"post":{"tags":["user"],"summary":"Create user","description":"This can only be done by the logged in user.","operationId":"createUser","consumes":["application/json"],"produces":["application/json","application/xml"],"parameters":[{"in":"body","name":"body","description":"Created user object","required":true,"schema":{"$ref":"#/definitions/User"}}],"responses":{"default":{"description":"successful operation"}}}}},"securityDefinitions":{"api_key":{"type":"apiKey","name":"api_key","in":"header"},"petstore_auth":{"type":"oauth2","authorizationUrl":"https://petstore.swagger.io/oauth/authorize","flow":"implicit","scopes":{"read:pets":"read your pets","write:pets":"modify pets in your account"}}},"definitions":{"ApiResponse":{"type":"object","properties":{"code":{"type":"integer","format":"int32"},"type":{"type":"string"},"message":{"type":"string"}}},"Category":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"}},"xml":{"name":"Category"}},"Pet":{"type":"object","required":["name","photoUrls"],"properties":{"id":{"type":"integer","format":"int64"},"category":{"$ref":"#/definitions/Category"},"name":{"type":"string","example":"doggie"},"photoUrls":{"type":"array","xml":{"wrapped":true},"items":{"type":"string","xml":{"name":"photoUrl"}}},"tags":{"type":"array","xml":{"wrapped":true},"items":{"xml":{"name":"tag"},"$ref":"#/definitions/Tag"}},"status":{"type":"string","description":"pet status in the store","enum":["available","pending","sold"]}},"xml":{"name":"Pet"}},"Tag":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"}},"xml":{"name":"Tag"}},"Order":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"petId":{"type":"integer","format":"int64"},"quantity":{"type":"integer","format":"int32"},"shipDate":{"type":"string","format":"date-time"},"status":{"type":"string","description":"Order Status","enum":["placed","approved","delivered"]},"complete":{"type":"boolean"}},"xml":{"name":"Order"}},"User":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"username":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"email":{"type":"string"},"password":{"type":"string"},"phone":{"type":"string"},"userStatus":{"type":"integer","format":"int32","description":"User Status"}},"xml":{"name":"User"}}},"externalDocs":{"description":"Find out more about Swagger","url":"http://swagger.io"}} \ No newline at end of file From dd82d66f9b870c9768b22e49530c816b1103ea0d Mon Sep 17 00:00:00 2001 From: GandalfsBooks <96147516+ianroydemo@users.noreply.github.com> Date: Tue, 26 Apr 2022 13:40:11 -0400 Subject: [PATCH 05/19] Create test --- catalog-service/swagger/v1/test | 1 + 1 file changed, 1 insertion(+) create mode 100644 catalog-service/swagger/v1/test diff --git a/catalog-service/swagger/v1/test b/catalog-service/swagger/v1/test new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/catalog-service/swagger/v1/test @@ -0,0 +1 @@ + From 69cb0026b0c634d43ed3340dec4449152ecc3f8c Mon Sep 17 00:00:00 2001 From: GandalfsBooks <96147516+ianroydemo@users.noreply.github.com> Date: Tue, 26 Apr 2022 13:40:26 -0400 Subject: [PATCH 06/19] Add files via upload --- catalog-service/swagger/v1/swagger.json | 1 + 1 file changed, 1 insertion(+) create mode 100644 catalog-service/swagger/v1/swagger.json diff --git a/catalog-service/swagger/v1/swagger.json b/catalog-service/swagger/v1/swagger.json new file mode 100644 index 00000000..84f510c1 --- /dev/null +++ b/catalog-service/swagger/v1/swagger.json @@ -0,0 +1 @@ +{"swagger":"2.0","info":{"description":"This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters.","version":"1.0.6","title":"Swagger Petstore","termsOfService":"http://swagger.io/terms/","contact":{"email":"apiteam@swagger.io"},"license":{"name":"Apache 2.0","url":"http://www.apache.org/licenses/LICENSE-2.0.html"}},"host":"petstore.swagger.io","basePath":"/v2","tags":[{"name":"pet","description":"Everything about your Pets","externalDocs":{"description":"Find out more","url":"http://swagger.io"}},{"name":"store","description":"Access to Petstore orders"},{"name":"user","description":"Operations about user","externalDocs":{"description":"Find out more about our store","url":"http://swagger.io"}}],"schemes":["https","http"],"paths":{"/pet/{petId}/uploadImage":{"post":{"tags":["pet"],"summary":"uploads an image","description":"","operationId":"uploadFile","consumes":["multipart/form-data"],"produces":["application/json"],"parameters":[{"name":"petId","in":"path","description":"ID of pet to update","required":true,"type":"integer","format":"int64"},{"name":"additionalMetadata","in":"formData","description":"Additional data to pass to server","required":false,"type":"string"},{"name":"file","in":"formData","description":"file to upload","required":false,"type":"file"}],"responses":{"200":{"description":"successful operation","schema":{"$ref":"#/definitions/ApiResponse"}}},"security":[{"petstore_auth":["write:pets","read:pets"]}]}},"/pet":{"post":{"tags":["pet"],"summary":"Add a new pet to the store","description":"","operationId":"addPet","consumes":["application/json","application/xml"],"produces":["application/json","application/xml"],"parameters":[{"in":"body","name":"body","description":"Pet object that needs to be added to the store","required":true,"schema":{"$ref":"#/definitions/Pet"}}],"responses":{"405":{"description":"Invalid input"}},"security":[{"petstore_auth":["write:pets","read:pets"]}]},"put":{"tags":["pet"],"summary":"Update an existing pet","description":"","operationId":"updatePet","consumes":["application/json","application/xml"],"produces":["application/json","application/xml"],"parameters":[{"in":"body","name":"body","description":"Pet object that needs to be added to the store","required":true,"schema":{"$ref":"#/definitions/Pet"}}],"responses":{"400":{"description":"Invalid ID supplied"},"404":{"description":"Pet not found"},"405":{"description":"Validation exception"}},"security":[{"petstore_auth":["write:pets","read:pets"]}]}},"/pet/findByStatus":{"get":{"tags":["pet"],"summary":"Finds Pets by status","description":"Multiple status values can be provided with comma separated strings","operationId":"findPetsByStatus","produces":["application/json","application/xml"],"parameters":[{"name":"status","in":"query","description":"Status values that need to be considered for filter","required":true,"type":"array","items":{"type":"string","enum":["available","pending","sold"],"default":"available"},"collectionFormat":"multi"}],"responses":{"200":{"description":"successful operation","schema":{"type":"array","items":{"$ref":"#/definitions/Pet"}}},"400":{"description":"Invalid status value"}},"security":[{"petstore_auth":["write:pets","read:pets"]}]}},"/pet/findByTags":{"get":{"tags":["pet"],"summary":"Finds Pets by tags","description":"Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.","operationId":"findPetsByTags","produces":["application/json","application/xml"],"parameters":[{"name":"tags","in":"query","description":"Tags to filter by","required":true,"type":"array","items":{"type":"string"},"collectionFormat":"multi"}],"responses":{"200":{"description":"successful operation","schema":{"type":"array","items":{"$ref":"#/definitions/Pet"}}},"400":{"description":"Invalid tag value"}},"security":[{"petstore_auth":["write:pets","read:pets"]}],"deprecated":true}},"/pet/{petId}":{"get":{"tags":["pet"],"summary":"Find pet by ID","description":"Returns a single pet","operationId":"getPetById","produces":["application/json","application/xml"],"parameters":[{"name":"petId","in":"path","description":"ID of pet to return","required":true,"type":"integer","format":"int64"}],"responses":{"200":{"description":"successful operation","schema":{"$ref":"#/definitions/Pet"}},"400":{"description":"Invalid ID supplied"},"404":{"description":"Pet not found"}},"security":[{"api_key":[]}]},"post":{"tags":["pet"],"summary":"Updates a pet in the store with form data","description":"","operationId":"updatePetWithForm","consumes":["application/x-www-form-urlencoded"],"produces":["application/json","application/xml"],"parameters":[{"name":"petId","in":"path","description":"ID of pet that needs to be updated","required":true,"type":"integer","format":"int64"},{"name":"name","in":"formData","description":"Updated name of the pet","required":false,"type":"string"},{"name":"status","in":"formData","description":"Updated status of the pet","required":false,"type":"string"}],"responses":{"405":{"description":"Invalid input"}},"security":[{"petstore_auth":["write:pets","read:pets"]}]},"delete":{"tags":["pet"],"summary":"Deletes a pet","description":"","operationId":"deletePet","produces":["application/json","application/xml"],"parameters":[{"name":"api_key","in":"header","required":false,"type":"string"},{"name":"petId","in":"path","description":"Pet id to delete","required":true,"type":"integer","format":"int64"}],"responses":{"400":{"description":"Invalid ID supplied"},"404":{"description":"Pet not found"}},"security":[{"petstore_auth":["write:pets","read:pets"]}]}},"/store/order":{"post":{"tags":["store"],"summary":"Place an order for a pet","description":"","operationId":"placeOrder","consumes":["application/json"],"produces":["application/json","application/xml"],"parameters":[{"in":"body","name":"body","description":"order placed for purchasing the pet","required":true,"schema":{"$ref":"#/definitions/Order"}}],"responses":{"200":{"description":"successful operation","schema":{"$ref":"#/definitions/Order"}},"400":{"description":"Invalid Order"}}}},"/store/order/{orderId}":{"get":{"tags":["store"],"summary":"Find purchase order by ID","description":"For valid response try integer IDs with value >= 1 and <= 10. Other values will generated exceptions","operationId":"getOrderById","produces":["application/json","application/xml"],"parameters":[{"name":"orderId","in":"path","description":"ID of pet that needs to be fetched","required":true,"type":"integer","maximum":10,"minimum":1,"format":"int64"}],"responses":{"200":{"description":"successful operation","schema":{"$ref":"#/definitions/Order"}},"400":{"description":"Invalid ID supplied"},"404":{"description":"Order not found"}}},"delete":{"tags":["store"],"summary":"Delete purchase order by ID","description":"For valid response try integer IDs with positive integer value. Negative or non-integer values will generate API errors","operationId":"deleteOrder","produces":["application/json","application/xml"],"parameters":[{"name":"orderId","in":"path","description":"ID of the order that needs to be deleted","required":true,"type":"integer","minimum":1,"format":"int64"}],"responses":{"400":{"description":"Invalid ID supplied"},"404":{"description":"Order not found"}}}},"/store/inventory":{"get":{"tags":["store"],"summary":"Returns pet inventories by status","description":"Returns a map of status codes to quantities","operationId":"getInventory","produces":["application/json"],"parameters":[],"responses":{"200":{"description":"successful operation","schema":{"type":"object","additionalProperties":{"type":"integer","format":"int32"}}}},"security":[{"api_key":[]}]}},"/user/createWithArray":{"post":{"tags":["user"],"summary":"Creates list of users with given input array","description":"","operationId":"createUsersWithArrayInput","consumes":["application/json"],"produces":["application/json","application/xml"],"parameters":[{"in":"body","name":"body","description":"List of user object","required":true,"schema":{"type":"array","items":{"$ref":"#/definitions/User"}}}],"responses":{"default":{"description":"successful operation"}}}},"/user/createWithList":{"post":{"tags":["user"],"summary":"Creates list of users with given input array","description":"","operationId":"createUsersWithListInput","consumes":["application/json"],"produces":["application/json","application/xml"],"parameters":[{"in":"body","name":"body","description":"List of user object","required":true,"schema":{"type":"array","items":{"$ref":"#/definitions/User"}}}],"responses":{"default":{"description":"successful operation"}}}},"/user/{username}":{"get":{"tags":["user"],"summary":"Get user by user name","description":"","operationId":"getUserByName","produces":["application/json","application/xml"],"parameters":[{"name":"username","in":"path","description":"The name that needs to be fetched. Use user1 for testing. ","required":true,"type":"string"}],"responses":{"200":{"description":"successful operation","schema":{"$ref":"#/definitions/User"}},"400":{"description":"Invalid username supplied"},"404":{"description":"User not found"}}},"put":{"tags":["user"],"summary":"Updated user","description":"This can only be done by the logged in user.","operationId":"updateUser","consumes":["application/json"],"produces":["application/json","application/xml"],"parameters":[{"name":"username","in":"path","description":"name that need to be updated","required":true,"type":"string"},{"in":"body","name":"body","description":"Updated user object","required":true,"schema":{"$ref":"#/definitions/User"}}],"responses":{"400":{"description":"Invalid user supplied"},"404":{"description":"User not found"}}},"delete":{"tags":["user"],"summary":"Delete user","description":"This can only be done by the logged in user.","operationId":"deleteUser","produces":["application/json","application/xml"],"parameters":[{"name":"username","in":"path","description":"The name that needs to be deleted","required":true,"type":"string"}],"responses":{"400":{"description":"Invalid username supplied"},"404":{"description":"User not found"}}}},"/user/login":{"get":{"tags":["user"],"summary":"Logs user into the system","description":"","operationId":"loginUser","produces":["application/json","application/xml"],"parameters":[{"name":"username","in":"query","description":"The user name for login","required":true,"type":"string"},{"name":"password","in":"query","description":"The password for login in clear text","required":true,"type":"string"}],"responses":{"200":{"description":"successful operation","headers":{"X-Expires-After":{"type":"string","format":"date-time","description":"date in UTC when token expires"},"X-Rate-Limit":{"type":"integer","format":"int32","description":"calls per hour allowed by the user"}},"schema":{"type":"string"}},"400":{"description":"Invalid username/password supplied"}}}},"/user/logout":{"get":{"tags":["user"],"summary":"Logs out current logged in user session","description":"","operationId":"logoutUser","produces":["application/json","application/xml"],"parameters":[],"responses":{"default":{"description":"successful operation"}}}},"/user":{"post":{"tags":["user"],"summary":"Create user","description":"This can only be done by the logged in user.","operationId":"createUser","consumes":["application/json"],"produces":["application/json","application/xml"],"parameters":[{"in":"body","name":"body","description":"Created user object","required":true,"schema":{"$ref":"#/definitions/User"}}],"responses":{"default":{"description":"successful operation"}}}}},"securityDefinitions":{"api_key":{"type":"apiKey","name":"api_key","in":"header"},"petstore_auth":{"type":"oauth2","authorizationUrl":"https://petstore.swagger.io/oauth/authorize","flow":"implicit","scopes":{"read:pets":"read your pets","write:pets":"modify pets in your account"}}},"definitions":{"ApiResponse":{"type":"object","properties":{"code":{"type":"integer","format":"int32"},"type":{"type":"string"},"message":{"type":"string"}}},"Category":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"}},"xml":{"name":"Category"}},"Pet":{"type":"object","required":["name","photoUrls"],"properties":{"id":{"type":"integer","format":"int64"},"category":{"$ref":"#/definitions/Category"},"name":{"type":"string","example":"doggie"},"photoUrls":{"type":"array","xml":{"wrapped":true},"items":{"type":"string","xml":{"name":"photoUrl"}}},"tags":{"type":"array","xml":{"wrapped":true},"items":{"xml":{"name":"tag"},"$ref":"#/definitions/Tag"}},"status":{"type":"string","description":"pet status in the store","enum":["available","pending","sold"]}},"xml":{"name":"Pet"}},"Tag":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"}},"xml":{"name":"Tag"}},"Order":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"petId":{"type":"integer","format":"int64"},"quantity":{"type":"integer","format":"int32"},"shipDate":{"type":"string","format":"date-time"},"status":{"type":"string","description":"Order Status","enum":["placed","approved","delivered"]},"complete":{"type":"boolean"}},"xml":{"name":"Order"}},"User":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"username":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"email":{"type":"string"},"password":{"type":"string"},"phone":{"type":"string"},"userStatus":{"type":"integer","format":"int32","description":"User Status"}},"xml":{"name":"User"}}},"externalDocs":{"description":"Find out more about Swagger","url":"http://swagger.io"}} \ No newline at end of file From 36508924d11336cf232b72ccbab5b9a930a9d514 Mon Sep 17 00:00:00 2001 From: GandalfsBooks <96147516+ianroydemo@users.noreply.github.com> Date: Tue, 26 Apr 2022 13:40:42 -0400 Subject: [PATCH 07/19] Delete swagger.json --- catalog-service/swagger.json | 1 - 1 file changed, 1 deletion(-) delete mode 100644 catalog-service/swagger.json diff --git a/catalog-service/swagger.json b/catalog-service/swagger.json deleted file mode 100644 index 84f510c1..00000000 --- a/catalog-service/swagger.json +++ /dev/null @@ -1 +0,0 @@ -{"swagger":"2.0","info":{"description":"This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters.","version":"1.0.6","title":"Swagger Petstore","termsOfService":"http://swagger.io/terms/","contact":{"email":"apiteam@swagger.io"},"license":{"name":"Apache 2.0","url":"http://www.apache.org/licenses/LICENSE-2.0.html"}},"host":"petstore.swagger.io","basePath":"/v2","tags":[{"name":"pet","description":"Everything about your Pets","externalDocs":{"description":"Find out more","url":"http://swagger.io"}},{"name":"store","description":"Access to Petstore orders"},{"name":"user","description":"Operations about user","externalDocs":{"description":"Find out more about our store","url":"http://swagger.io"}}],"schemes":["https","http"],"paths":{"/pet/{petId}/uploadImage":{"post":{"tags":["pet"],"summary":"uploads an image","description":"","operationId":"uploadFile","consumes":["multipart/form-data"],"produces":["application/json"],"parameters":[{"name":"petId","in":"path","description":"ID of pet to update","required":true,"type":"integer","format":"int64"},{"name":"additionalMetadata","in":"formData","description":"Additional data to pass to server","required":false,"type":"string"},{"name":"file","in":"formData","description":"file to upload","required":false,"type":"file"}],"responses":{"200":{"description":"successful operation","schema":{"$ref":"#/definitions/ApiResponse"}}},"security":[{"petstore_auth":["write:pets","read:pets"]}]}},"/pet":{"post":{"tags":["pet"],"summary":"Add a new pet to the store","description":"","operationId":"addPet","consumes":["application/json","application/xml"],"produces":["application/json","application/xml"],"parameters":[{"in":"body","name":"body","description":"Pet object that needs to be added to the store","required":true,"schema":{"$ref":"#/definitions/Pet"}}],"responses":{"405":{"description":"Invalid input"}},"security":[{"petstore_auth":["write:pets","read:pets"]}]},"put":{"tags":["pet"],"summary":"Update an existing pet","description":"","operationId":"updatePet","consumes":["application/json","application/xml"],"produces":["application/json","application/xml"],"parameters":[{"in":"body","name":"body","description":"Pet object that needs to be added to the store","required":true,"schema":{"$ref":"#/definitions/Pet"}}],"responses":{"400":{"description":"Invalid ID supplied"},"404":{"description":"Pet not found"},"405":{"description":"Validation exception"}},"security":[{"petstore_auth":["write:pets","read:pets"]}]}},"/pet/findByStatus":{"get":{"tags":["pet"],"summary":"Finds Pets by status","description":"Multiple status values can be provided with comma separated strings","operationId":"findPetsByStatus","produces":["application/json","application/xml"],"parameters":[{"name":"status","in":"query","description":"Status values that need to be considered for filter","required":true,"type":"array","items":{"type":"string","enum":["available","pending","sold"],"default":"available"},"collectionFormat":"multi"}],"responses":{"200":{"description":"successful operation","schema":{"type":"array","items":{"$ref":"#/definitions/Pet"}}},"400":{"description":"Invalid status value"}},"security":[{"petstore_auth":["write:pets","read:pets"]}]}},"/pet/findByTags":{"get":{"tags":["pet"],"summary":"Finds Pets by tags","description":"Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.","operationId":"findPetsByTags","produces":["application/json","application/xml"],"parameters":[{"name":"tags","in":"query","description":"Tags to filter by","required":true,"type":"array","items":{"type":"string"},"collectionFormat":"multi"}],"responses":{"200":{"description":"successful operation","schema":{"type":"array","items":{"$ref":"#/definitions/Pet"}}},"400":{"description":"Invalid tag value"}},"security":[{"petstore_auth":["write:pets","read:pets"]}],"deprecated":true}},"/pet/{petId}":{"get":{"tags":["pet"],"summary":"Find pet by ID","description":"Returns a single pet","operationId":"getPetById","produces":["application/json","application/xml"],"parameters":[{"name":"petId","in":"path","description":"ID of pet to return","required":true,"type":"integer","format":"int64"}],"responses":{"200":{"description":"successful operation","schema":{"$ref":"#/definitions/Pet"}},"400":{"description":"Invalid ID supplied"},"404":{"description":"Pet not found"}},"security":[{"api_key":[]}]},"post":{"tags":["pet"],"summary":"Updates a pet in the store with form data","description":"","operationId":"updatePetWithForm","consumes":["application/x-www-form-urlencoded"],"produces":["application/json","application/xml"],"parameters":[{"name":"petId","in":"path","description":"ID of pet that needs to be updated","required":true,"type":"integer","format":"int64"},{"name":"name","in":"formData","description":"Updated name of the pet","required":false,"type":"string"},{"name":"status","in":"formData","description":"Updated status of the pet","required":false,"type":"string"}],"responses":{"405":{"description":"Invalid input"}},"security":[{"petstore_auth":["write:pets","read:pets"]}]},"delete":{"tags":["pet"],"summary":"Deletes a pet","description":"","operationId":"deletePet","produces":["application/json","application/xml"],"parameters":[{"name":"api_key","in":"header","required":false,"type":"string"},{"name":"petId","in":"path","description":"Pet id to delete","required":true,"type":"integer","format":"int64"}],"responses":{"400":{"description":"Invalid ID supplied"},"404":{"description":"Pet not found"}},"security":[{"petstore_auth":["write:pets","read:pets"]}]}},"/store/order":{"post":{"tags":["store"],"summary":"Place an order for a pet","description":"","operationId":"placeOrder","consumes":["application/json"],"produces":["application/json","application/xml"],"parameters":[{"in":"body","name":"body","description":"order placed for purchasing the pet","required":true,"schema":{"$ref":"#/definitions/Order"}}],"responses":{"200":{"description":"successful operation","schema":{"$ref":"#/definitions/Order"}},"400":{"description":"Invalid Order"}}}},"/store/order/{orderId}":{"get":{"tags":["store"],"summary":"Find purchase order by ID","description":"For valid response try integer IDs with value >= 1 and <= 10. Other values will generated exceptions","operationId":"getOrderById","produces":["application/json","application/xml"],"parameters":[{"name":"orderId","in":"path","description":"ID of pet that needs to be fetched","required":true,"type":"integer","maximum":10,"minimum":1,"format":"int64"}],"responses":{"200":{"description":"successful operation","schema":{"$ref":"#/definitions/Order"}},"400":{"description":"Invalid ID supplied"},"404":{"description":"Order not found"}}},"delete":{"tags":["store"],"summary":"Delete purchase order by ID","description":"For valid response try integer IDs with positive integer value. Negative or non-integer values will generate API errors","operationId":"deleteOrder","produces":["application/json","application/xml"],"parameters":[{"name":"orderId","in":"path","description":"ID of the order that needs to be deleted","required":true,"type":"integer","minimum":1,"format":"int64"}],"responses":{"400":{"description":"Invalid ID supplied"},"404":{"description":"Order not found"}}}},"/store/inventory":{"get":{"tags":["store"],"summary":"Returns pet inventories by status","description":"Returns a map of status codes to quantities","operationId":"getInventory","produces":["application/json"],"parameters":[],"responses":{"200":{"description":"successful operation","schema":{"type":"object","additionalProperties":{"type":"integer","format":"int32"}}}},"security":[{"api_key":[]}]}},"/user/createWithArray":{"post":{"tags":["user"],"summary":"Creates list of users with given input array","description":"","operationId":"createUsersWithArrayInput","consumes":["application/json"],"produces":["application/json","application/xml"],"parameters":[{"in":"body","name":"body","description":"List of user object","required":true,"schema":{"type":"array","items":{"$ref":"#/definitions/User"}}}],"responses":{"default":{"description":"successful operation"}}}},"/user/createWithList":{"post":{"tags":["user"],"summary":"Creates list of users with given input array","description":"","operationId":"createUsersWithListInput","consumes":["application/json"],"produces":["application/json","application/xml"],"parameters":[{"in":"body","name":"body","description":"List of user object","required":true,"schema":{"type":"array","items":{"$ref":"#/definitions/User"}}}],"responses":{"default":{"description":"successful operation"}}}},"/user/{username}":{"get":{"tags":["user"],"summary":"Get user by user name","description":"","operationId":"getUserByName","produces":["application/json","application/xml"],"parameters":[{"name":"username","in":"path","description":"The name that needs to be fetched. Use user1 for testing. ","required":true,"type":"string"}],"responses":{"200":{"description":"successful operation","schema":{"$ref":"#/definitions/User"}},"400":{"description":"Invalid username supplied"},"404":{"description":"User not found"}}},"put":{"tags":["user"],"summary":"Updated user","description":"This can only be done by the logged in user.","operationId":"updateUser","consumes":["application/json"],"produces":["application/json","application/xml"],"parameters":[{"name":"username","in":"path","description":"name that need to be updated","required":true,"type":"string"},{"in":"body","name":"body","description":"Updated user object","required":true,"schema":{"$ref":"#/definitions/User"}}],"responses":{"400":{"description":"Invalid user supplied"},"404":{"description":"User not found"}}},"delete":{"tags":["user"],"summary":"Delete user","description":"This can only be done by the logged in user.","operationId":"deleteUser","produces":["application/json","application/xml"],"parameters":[{"name":"username","in":"path","description":"The name that needs to be deleted","required":true,"type":"string"}],"responses":{"400":{"description":"Invalid username supplied"},"404":{"description":"User not found"}}}},"/user/login":{"get":{"tags":["user"],"summary":"Logs user into the system","description":"","operationId":"loginUser","produces":["application/json","application/xml"],"parameters":[{"name":"username","in":"query","description":"The user name for login","required":true,"type":"string"},{"name":"password","in":"query","description":"The password for login in clear text","required":true,"type":"string"}],"responses":{"200":{"description":"successful operation","headers":{"X-Expires-After":{"type":"string","format":"date-time","description":"date in UTC when token expires"},"X-Rate-Limit":{"type":"integer","format":"int32","description":"calls per hour allowed by the user"}},"schema":{"type":"string"}},"400":{"description":"Invalid username/password supplied"}}}},"/user/logout":{"get":{"tags":["user"],"summary":"Logs out current logged in user session","description":"","operationId":"logoutUser","produces":["application/json","application/xml"],"parameters":[],"responses":{"default":{"description":"successful operation"}}}},"/user":{"post":{"tags":["user"],"summary":"Create user","description":"This can only be done by the logged in user.","operationId":"createUser","consumes":["application/json"],"produces":["application/json","application/xml"],"parameters":[{"in":"body","name":"body","description":"Created user object","required":true,"schema":{"$ref":"#/definitions/User"}}],"responses":{"default":{"description":"successful operation"}}}}},"securityDefinitions":{"api_key":{"type":"apiKey","name":"api_key","in":"header"},"petstore_auth":{"type":"oauth2","authorizationUrl":"https://petstore.swagger.io/oauth/authorize","flow":"implicit","scopes":{"read:pets":"read your pets","write:pets":"modify pets in your account"}}},"definitions":{"ApiResponse":{"type":"object","properties":{"code":{"type":"integer","format":"int32"},"type":{"type":"string"},"message":{"type":"string"}}},"Category":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"}},"xml":{"name":"Category"}},"Pet":{"type":"object","required":["name","photoUrls"],"properties":{"id":{"type":"integer","format":"int64"},"category":{"$ref":"#/definitions/Category"},"name":{"type":"string","example":"doggie"},"photoUrls":{"type":"array","xml":{"wrapped":true},"items":{"type":"string","xml":{"name":"photoUrl"}}},"tags":{"type":"array","xml":{"wrapped":true},"items":{"xml":{"name":"tag"},"$ref":"#/definitions/Tag"}},"status":{"type":"string","description":"pet status in the store","enum":["available","pending","sold"]}},"xml":{"name":"Pet"}},"Tag":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"}},"xml":{"name":"Tag"}},"Order":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"petId":{"type":"integer","format":"int64"},"quantity":{"type":"integer","format":"int32"},"shipDate":{"type":"string","format":"date-time"},"status":{"type":"string","description":"Order Status","enum":["placed","approved","delivered"]},"complete":{"type":"boolean"}},"xml":{"name":"Order"}},"User":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"username":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"email":{"type":"string"},"password":{"type":"string"},"phone":{"type":"string"},"userStatus":{"type":"integer","format":"int32","description":"User Status"}},"xml":{"name":"User"}}},"externalDocs":{"description":"Find out more about Swagger","url":"http://swagger.io"}} \ No newline at end of file From f2dffb1120b2a78c80ad0e198df22c71907d19e7 Mon Sep 17 00:00:00 2001 From: GandalfsBooks <96147516+ianroydemo@users.noreply.github.com> Date: Thu, 28 Apr 2022 16:42:59 -0400 Subject: [PATCH 08/19] Update swagger.json --- catalog-service/swagger/v1/swagger.json | 1055 ++++++++++++++++++++++- 1 file changed, 1054 insertions(+), 1 deletion(-) diff --git a/catalog-service/swagger/v1/swagger.json b/catalog-service/swagger/v1/swagger.json index 84f510c1..daeb7f6b 100644 --- a/catalog-service/swagger/v1/swagger.json +++ b/catalog-service/swagger/v1/swagger.json @@ -1 +1,1054 @@ -{"swagger":"2.0","info":{"description":"This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters.","version":"1.0.6","title":"Swagger Petstore","termsOfService":"http://swagger.io/terms/","contact":{"email":"apiteam@swagger.io"},"license":{"name":"Apache 2.0","url":"http://www.apache.org/licenses/LICENSE-2.0.html"}},"host":"petstore.swagger.io","basePath":"/v2","tags":[{"name":"pet","description":"Everything about your Pets","externalDocs":{"description":"Find out more","url":"http://swagger.io"}},{"name":"store","description":"Access to Petstore orders"},{"name":"user","description":"Operations about user","externalDocs":{"description":"Find out more about our store","url":"http://swagger.io"}}],"schemes":["https","http"],"paths":{"/pet/{petId}/uploadImage":{"post":{"tags":["pet"],"summary":"uploads an image","description":"","operationId":"uploadFile","consumes":["multipart/form-data"],"produces":["application/json"],"parameters":[{"name":"petId","in":"path","description":"ID of pet to update","required":true,"type":"integer","format":"int64"},{"name":"additionalMetadata","in":"formData","description":"Additional data to pass to server","required":false,"type":"string"},{"name":"file","in":"formData","description":"file to upload","required":false,"type":"file"}],"responses":{"200":{"description":"successful operation","schema":{"$ref":"#/definitions/ApiResponse"}}},"security":[{"petstore_auth":["write:pets","read:pets"]}]}},"/pet":{"post":{"tags":["pet"],"summary":"Add a new pet to the store","description":"","operationId":"addPet","consumes":["application/json","application/xml"],"produces":["application/json","application/xml"],"parameters":[{"in":"body","name":"body","description":"Pet object that needs to be added to the store","required":true,"schema":{"$ref":"#/definitions/Pet"}}],"responses":{"405":{"description":"Invalid input"}},"security":[{"petstore_auth":["write:pets","read:pets"]}]},"put":{"tags":["pet"],"summary":"Update an existing pet","description":"","operationId":"updatePet","consumes":["application/json","application/xml"],"produces":["application/json","application/xml"],"parameters":[{"in":"body","name":"body","description":"Pet object that needs to be added to the store","required":true,"schema":{"$ref":"#/definitions/Pet"}}],"responses":{"400":{"description":"Invalid ID supplied"},"404":{"description":"Pet not found"},"405":{"description":"Validation exception"}},"security":[{"petstore_auth":["write:pets","read:pets"]}]}},"/pet/findByStatus":{"get":{"tags":["pet"],"summary":"Finds Pets by status","description":"Multiple status values can be provided with comma separated strings","operationId":"findPetsByStatus","produces":["application/json","application/xml"],"parameters":[{"name":"status","in":"query","description":"Status values that need to be considered for filter","required":true,"type":"array","items":{"type":"string","enum":["available","pending","sold"],"default":"available"},"collectionFormat":"multi"}],"responses":{"200":{"description":"successful operation","schema":{"type":"array","items":{"$ref":"#/definitions/Pet"}}},"400":{"description":"Invalid status value"}},"security":[{"petstore_auth":["write:pets","read:pets"]}]}},"/pet/findByTags":{"get":{"tags":["pet"],"summary":"Finds Pets by tags","description":"Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.","operationId":"findPetsByTags","produces":["application/json","application/xml"],"parameters":[{"name":"tags","in":"query","description":"Tags to filter by","required":true,"type":"array","items":{"type":"string"},"collectionFormat":"multi"}],"responses":{"200":{"description":"successful operation","schema":{"type":"array","items":{"$ref":"#/definitions/Pet"}}},"400":{"description":"Invalid tag value"}},"security":[{"petstore_auth":["write:pets","read:pets"]}],"deprecated":true}},"/pet/{petId}":{"get":{"tags":["pet"],"summary":"Find pet by ID","description":"Returns a single pet","operationId":"getPetById","produces":["application/json","application/xml"],"parameters":[{"name":"petId","in":"path","description":"ID of pet to return","required":true,"type":"integer","format":"int64"}],"responses":{"200":{"description":"successful operation","schema":{"$ref":"#/definitions/Pet"}},"400":{"description":"Invalid ID supplied"},"404":{"description":"Pet not found"}},"security":[{"api_key":[]}]},"post":{"tags":["pet"],"summary":"Updates a pet in the store with form data","description":"","operationId":"updatePetWithForm","consumes":["application/x-www-form-urlencoded"],"produces":["application/json","application/xml"],"parameters":[{"name":"petId","in":"path","description":"ID of pet that needs to be updated","required":true,"type":"integer","format":"int64"},{"name":"name","in":"formData","description":"Updated name of the pet","required":false,"type":"string"},{"name":"status","in":"formData","description":"Updated status of the pet","required":false,"type":"string"}],"responses":{"405":{"description":"Invalid input"}},"security":[{"petstore_auth":["write:pets","read:pets"]}]},"delete":{"tags":["pet"],"summary":"Deletes a pet","description":"","operationId":"deletePet","produces":["application/json","application/xml"],"parameters":[{"name":"api_key","in":"header","required":false,"type":"string"},{"name":"petId","in":"path","description":"Pet id to delete","required":true,"type":"integer","format":"int64"}],"responses":{"400":{"description":"Invalid ID supplied"},"404":{"description":"Pet not found"}},"security":[{"petstore_auth":["write:pets","read:pets"]}]}},"/store/order":{"post":{"tags":["store"],"summary":"Place an order for a pet","description":"","operationId":"placeOrder","consumes":["application/json"],"produces":["application/json","application/xml"],"parameters":[{"in":"body","name":"body","description":"order placed for purchasing the pet","required":true,"schema":{"$ref":"#/definitions/Order"}}],"responses":{"200":{"description":"successful operation","schema":{"$ref":"#/definitions/Order"}},"400":{"description":"Invalid Order"}}}},"/store/order/{orderId}":{"get":{"tags":["store"],"summary":"Find purchase order by ID","description":"For valid response try integer IDs with value >= 1 and <= 10. Other values will generated exceptions","operationId":"getOrderById","produces":["application/json","application/xml"],"parameters":[{"name":"orderId","in":"path","description":"ID of pet that needs to be fetched","required":true,"type":"integer","maximum":10,"minimum":1,"format":"int64"}],"responses":{"200":{"description":"successful operation","schema":{"$ref":"#/definitions/Order"}},"400":{"description":"Invalid ID supplied"},"404":{"description":"Order not found"}}},"delete":{"tags":["store"],"summary":"Delete purchase order by ID","description":"For valid response try integer IDs with positive integer value. Negative or non-integer values will generate API errors","operationId":"deleteOrder","produces":["application/json","application/xml"],"parameters":[{"name":"orderId","in":"path","description":"ID of the order that needs to be deleted","required":true,"type":"integer","minimum":1,"format":"int64"}],"responses":{"400":{"description":"Invalid ID supplied"},"404":{"description":"Order not found"}}}},"/store/inventory":{"get":{"tags":["store"],"summary":"Returns pet inventories by status","description":"Returns a map of status codes to quantities","operationId":"getInventory","produces":["application/json"],"parameters":[],"responses":{"200":{"description":"successful operation","schema":{"type":"object","additionalProperties":{"type":"integer","format":"int32"}}}},"security":[{"api_key":[]}]}},"/user/createWithArray":{"post":{"tags":["user"],"summary":"Creates list of users with given input array","description":"","operationId":"createUsersWithArrayInput","consumes":["application/json"],"produces":["application/json","application/xml"],"parameters":[{"in":"body","name":"body","description":"List of user object","required":true,"schema":{"type":"array","items":{"$ref":"#/definitions/User"}}}],"responses":{"default":{"description":"successful operation"}}}},"/user/createWithList":{"post":{"tags":["user"],"summary":"Creates list of users with given input array","description":"","operationId":"createUsersWithListInput","consumes":["application/json"],"produces":["application/json","application/xml"],"parameters":[{"in":"body","name":"body","description":"List of user object","required":true,"schema":{"type":"array","items":{"$ref":"#/definitions/User"}}}],"responses":{"default":{"description":"successful operation"}}}},"/user/{username}":{"get":{"tags":["user"],"summary":"Get user by user name","description":"","operationId":"getUserByName","produces":["application/json","application/xml"],"parameters":[{"name":"username","in":"path","description":"The name that needs to be fetched. Use user1 for testing. ","required":true,"type":"string"}],"responses":{"200":{"description":"successful operation","schema":{"$ref":"#/definitions/User"}},"400":{"description":"Invalid username supplied"},"404":{"description":"User not found"}}},"put":{"tags":["user"],"summary":"Updated user","description":"This can only be done by the logged in user.","operationId":"updateUser","consumes":["application/json"],"produces":["application/json","application/xml"],"parameters":[{"name":"username","in":"path","description":"name that need to be updated","required":true,"type":"string"},{"in":"body","name":"body","description":"Updated user object","required":true,"schema":{"$ref":"#/definitions/User"}}],"responses":{"400":{"description":"Invalid user supplied"},"404":{"description":"User not found"}}},"delete":{"tags":["user"],"summary":"Delete user","description":"This can only be done by the logged in user.","operationId":"deleteUser","produces":["application/json","application/xml"],"parameters":[{"name":"username","in":"path","description":"The name that needs to be deleted","required":true,"type":"string"}],"responses":{"400":{"description":"Invalid username supplied"},"404":{"description":"User not found"}}}},"/user/login":{"get":{"tags":["user"],"summary":"Logs user into the system","description":"","operationId":"loginUser","produces":["application/json","application/xml"],"parameters":[{"name":"username","in":"query","description":"The user name for login","required":true,"type":"string"},{"name":"password","in":"query","description":"The password for login in clear text","required":true,"type":"string"}],"responses":{"200":{"description":"successful operation","headers":{"X-Expires-After":{"type":"string","format":"date-time","description":"date in UTC when token expires"},"X-Rate-Limit":{"type":"integer","format":"int32","description":"calls per hour allowed by the user"}},"schema":{"type":"string"}},"400":{"description":"Invalid username/password supplied"}}}},"/user/logout":{"get":{"tags":["user"],"summary":"Logs out current logged in user session","description":"","operationId":"logoutUser","produces":["application/json","application/xml"],"parameters":[],"responses":{"default":{"description":"successful operation"}}}},"/user":{"post":{"tags":["user"],"summary":"Create user","description":"This can only be done by the logged in user.","operationId":"createUser","consumes":["application/json"],"produces":["application/json","application/xml"],"parameters":[{"in":"body","name":"body","description":"Created user object","required":true,"schema":{"$ref":"#/definitions/User"}}],"responses":{"default":{"description":"successful operation"}}}}},"securityDefinitions":{"api_key":{"type":"apiKey","name":"api_key","in":"header"},"petstore_auth":{"type":"oauth2","authorizationUrl":"https://petstore.swagger.io/oauth/authorize","flow":"implicit","scopes":{"read:pets":"read your pets","write:pets":"modify pets in your account"}}},"definitions":{"ApiResponse":{"type":"object","properties":{"code":{"type":"integer","format":"int32"},"type":{"type":"string"},"message":{"type":"string"}}},"Category":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"}},"xml":{"name":"Category"}},"Pet":{"type":"object","required":["name","photoUrls"],"properties":{"id":{"type":"integer","format":"int64"},"category":{"$ref":"#/definitions/Category"},"name":{"type":"string","example":"doggie"},"photoUrls":{"type":"array","xml":{"wrapped":true},"items":{"type":"string","xml":{"name":"photoUrl"}}},"tags":{"type":"array","xml":{"wrapped":true},"items":{"xml":{"name":"tag"},"$ref":"#/definitions/Tag"}},"status":{"type":"string","description":"pet status in the store","enum":["available","pending","sold"]}},"xml":{"name":"Pet"}},"Tag":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"}},"xml":{"name":"Tag"}},"Order":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"petId":{"type":"integer","format":"int64"},"quantity":{"type":"integer","format":"int32"},"shipDate":{"type":"string","format":"date-time"},"status":{"type":"string","description":"Order Status","enum":["placed","approved","delivered"]},"complete":{"type":"boolean"}},"xml":{"name":"Order"}},"User":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"username":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"email":{"type":"string"},"password":{"type":"string"},"phone":{"type":"string"},"userStatus":{"type":"integer","format":"int32","description":"User Status"}},"xml":{"name":"User"}}},"externalDocs":{"description":"Find out more about Swagger","url":"http://swagger.io"}} \ No newline at end of file +{ + "swagger": "2.0", + "info": { + "description": "This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters.", + "version": "1.0.6", + "title": "Swagger Petstore", + "termsOfService": "http://swagger.io/terms/", + "contact": { + "email": "apiteam@swagger.io" + }, + "license": { + "name": "Apache 2.0", + "url": "http://www.apache.org/licenses/LICENSE-2.0.html" + } + }, + "host": "petstore.swagger.io", + "basePath": "/v2", + "tags": [ + { + "name": "pet", + "description": "Everything about your Pets", + "externalDocs": { + "description": "Find out more", + "url": "http://swagger.io" + } + }, + { + "name": "store", + "description": "Access to Petstore orders" + }, + { + "name": "user", + "description": "Operations about user", + "externalDocs": { + "description": "Find out more about our store", + "url": "http://swagger.io" + } + } + ], + "schemes": [ + "https", + "http" + ], + "paths": { + "/pet/{petId}/uploadImage": { + "post": { + "tags": [ + "pet" + ], + "summary": "uploads an image", + "description": "", + "operationId": "uploadFile", + "consumes": [ + "multipart/form-data" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "name": "petId", + "in": "path", + "description": "ID of pet to update", + "required": true, + "type": "integer", + "format": "int64" + }, + { + "name": "additionalMetadata", + "in": "formData", + "description": "Additional data to pass to server", + "required": false, + "type": "string" + }, + { + "name": "file", + "in": "formData", + "description": "file to upload", + "required": false, + "type": "file" + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/definitions/ApiResponse" + } + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + } + }, + "/pet": { + "post": { + "tags": [ + "pet" + ], + "summary": "Add a new pet to the store", + "description": "", + "operationId": "addPet", + "consumes": [ + "application/json", + "application/xml" + ], + "produces": [ + "application/json", + "application/xml" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "description": "Pet object that needs to be added to the store", + "required": true, + "schema": { + "$ref": "#/definitions/Pet" + } + } + ], + "responses": { + "405": { + "description": "Invalid input" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + }, + "put": { + "tags": [ + "pet" + ], + "summary": "Update an existing pet", + "description": "", + "operationId": "updatePet", + "consumes": [ + "application/json", + "application/xml" + ], + "produces": [ + "application/json", + "application/xml" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "description": "Pet object that needs to be added to the store", + "required": true, + "schema": { + "$ref": "#/definitions/Pet" + } + } + ], + "responses": { + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Pet not found" + }, + "405": { + "description": "Validation exception" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + } + }, + "/pet/findByStatus": { + "get": { + "tags": [ + "pet" + ], + "summary": "Finds Pets by status", + "description": "Multiple status values can be provided with comma separated strings", + "operationId": "findPetsByStatus", + "produces": [ + "application/json", + "application/xml" + ], + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Status values that need to be considered for filter", + "required": true, + "type": "array", + "items": { + "type": "string", + "enum": [ + "available", + "pending", + "sold" + ], + "default": "available" + }, + "collectionFormat": "multi" + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/Pet" + } + } + }, + "400": { + "description": "Invalid status value" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + } + }, + "/pet/findByTags": { + "get": { + "tags": [ + "pet" + ], + "summary": "Finds Pets by tags", + "description": "Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.", + "operationId": "findPetsByTags", + "produces": [ + "application/json", + "application/xml" + ], + "parameters": [ + { + "name": "tags", + "in": "query", + "description": "Tags to filter by", + "required": true, + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "multi" + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/Pet" + } + } + }, + "400": { + "description": "Invalid tag value" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ], + "deprecated": true + } + }, + "/pet/{petId}": { + "get": { + "tags": [ + "pet" + ], + "summary": "Find pet by ID", + "description": "Returns a single pet", + "operationId": "getPetById", + "produces": [ + "application/json", + "application/xml" + ], + "parameters": [ + { + "name": "petId", + "in": "path", + "description": "ID of pet to return", + "required": true, + "type": "integer", + "format": "int64" + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/definitions/Pet" + } + }, + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Pet not found" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "post": { + "tags": [ + "pet" + ], + "summary": "Updates a pet in the store with form data", + "description": "", + "operationId": "updatePetWithForm", + "consumes": [ + "application/x-www-form-urlencoded" + ], + "produces": [ + "application/json", + "application/xml" + ], + "parameters": [ + { + "name": "petId", + "in": "path", + "description": "ID of pet that needs to be updated", + "required": true, + "type": "integer", + "format": "int64" + }, + { + "name": "name", + "in": "formData", + "description": "Updated name of the pet", + "required": false, + "type": "string" + }, + { + "name": "status", + "in": "formData", + "description": "Updated status of the pet", + "required": false, + "type": "string" + } + ], + "responses": { + "405": { + "description": "Invalid input" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + }, + "delete": { + "tags": [ + "pet" + ], + "summary": "Deletes a pet", + "description": "", + "operationId": "deletePet", + "produces": [ + "application/json", + "application/xml" + ], + "parameters": [ + { + "name": "api_key", + "in": "header", + "required": false, + "type": "string" + }, + { + "name": "petId", + "in": "path", + "description": "Pet id to delete", + "required": true, + "type": "integer", + "format": "int64" + } + ], + "responses": { + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Pet not found" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + } + }, + "/store/order": { + "post": { + "tags": [ + "store" + ], + "summary": "Place an order for a pet", + "description": "", + "operationId": "placeOrder", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json", + "application/xml" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "description": "order placed for purchasing the pet", + "required": true, + "schema": { + "$ref": "#/definitions/Order" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/definitions/Order" + } + }, + "400": { + "description": "Invalid Order" + } + } + } + }, + "/store/order/{orderId}": { + "get": { + "tags": [ + "store" + ], + "summary": "Find purchase order by ID", + "description": "For valid response try integer IDs with value >= 1 and <= 10. Other values will generated exceptions", + "operationId": "getOrderById", + "produces": [ + "application/json", + "application/xml" + ], + "parameters": [ + { + "name": "orderId", + "in": "path", + "description": "ID of pet that needs to be fetched", + "required": true, + "type": "integer", + "maximum": 10, + "minimum": 1, + "format": "int64" + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/definitions/Order" + } + }, + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Order not found" + } + } + }, + "delete": { + "tags": [ + "store" + ], + "summary": "Delete purchase order by ID", + "description": "For valid response try integer IDs with positive integer value. Negative or non-integer values will generate API errors", + "operationId": "deleteOrder", + "produces": [ + "application/json", + "application/xml" + ], + "parameters": [ + { + "name": "orderId", + "in": "path", + "description": "ID of the order that needs to be deleted", + "required": true, + "type": "integer", + "minimum": 1, + "format": "int64" + } + ], + "responses": { + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Order not found" + } + } + } + }, + "/store/inventory": { + "get": { + "tags": [ + "store" + ], + "summary": "Returns pet inventories by status", + "description": "Returns a map of status codes to quantities", + "operationId": "getInventory", + "produces": [ + "application/json" + ], + "parameters": [], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "type": "object", + "additionalProperties": { + "type": "integer", + "format": "int32" + } + } + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/user/createWithArray": { + "post": { + "tags": [ + "user" + ], + "summary": "Creates list of users with given input array", + "description": "", + "operationId": "createUsersWithArrayInput", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json", + "application/xml" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "description": "List of user object", + "required": true, + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/User" + } + } + } + ], + "responses": { + "default": { + "description": "successful operation" + } + } + } + }, + "/user/createWithList": { + "post": { + "tags": [ + "user" + ], + "summary": "Creates list of users with given input array", + "description": "", + "operationId": "createUsersWithListInput", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json", + "application/xml" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "description": "List of user object", + "required": true, + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/User" + } + } + } + ], + "responses": { + "default": { + "description": "successful operation" + } + } + } + }, + "/user/{username}": { + "get": { + "tags": [ + "user" + ], + "summary": "Get user by user name", + "description": "", + "operationId": "getUserByName", + "produces": [ + "application/json", + "application/xml" + ], + "parameters": [ + { + "name": "username", + "in": "path", + "description": "The name that needs to be fetched. Use user1 for testing. ", + "required": true, + "type": "string" + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/definitions/User" + } + }, + "400": { + "description": "Invalid username supplied" + }, + "404": { + "description": "User not found" + } + } + }, + "put": { + "tags": [ + "user" + ], + "summary": "Updated user", + "description": "This can only be done by the logged in user.", + "operationId": "updateUser", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json", + "application/xml" + ], + "parameters": [ + { + "name": "username", + "in": "path", + "description": "name that need to be updated", + "required": true, + "type": "string" + }, + { + "in": "body", + "name": "body", + "description": "Updated user object", + "required": true, + "schema": { + "$ref": "#/definitions/User" + } + } + ], + "responses": { + "400": { + "description": "Invalid user supplied" + }, + "404": { + "description": "User not found" + } + } + }, + "delete": { + "tags": [ + "user" + ], + "summary": "Delete user", + "description": "This can only be done by the logged in user.", + "operationId": "deleteUser", + "produces": [ + "application/json", + "application/xml" + ], + "parameters": [ + { + "name": "username", + "in": "path", + "description": "The name that needs to be deleted", + "required": true, + "type": "string" + } + ], + "responses": { + "400": { + "description": "Invalid username supplied" + }, + "404": { + "description": "User not found" + } + } + } + }, + "/user/login": { + "get": { + "tags": [ + "user" + ], + "summary": "Logs user into the system", + "description": "", + "operationId": "loginUser", + "produces": [ + "application/json", + "application/xml" + ], + "parameters": [ + { + "name": "username", + "in": "query", + "description": "The user name for login", + "required": true, + "type": "string" + }, + { + "name": "password", + "in": "query", + "description": "The password for login in clear text", + "required": true, + "type": "string" + } + ], + "responses": { + "200": { + "description": "successful operation", + "headers": { + "X-Expires-After": { + "type": "string", + "format": "date-time", + "description": "date in UTC when token expires" + }, + "X-Rate-Limit": { + "type": "integer", + "format": "int32", + "description": "calls per hour allowed by the user" + } + }, + "schema": { + "type": "string" + } + }, + "400": { + "description": "Invalid username/password supplied" + } + } + } + }, + "/user/logout": { + "get": { + "tags": [ + "user" + ], + "summary": "Logs out current logged in user session", + "description": "", + "operationId": "logoutUser", + "produces": [ + "application/json", + "application/xml" + ], + "parameters": [], + "responses": { + "default": { + "description": "successful operation" + } + } + } + }, + "/user": { + "post": { + "tags": [ + "user" + ], + "summary": "Create user", + "description": "This can only be done by the logged in user.", + "operationId": "createUser", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json", + "application/xml" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "description": "Created user object", + "required": true, + "schema": { + "$ref": "#/definitions/User" + } + } + ], + "responses": { + "default": { + "description": "successful operation" + } + } + } + } + }, + "securityDefinitions": { + "api_key": { + "type": "apiKey", + "name": "api_key", + "in": "header" + }, + "petstore_auth": { + "type": "oauth2", + "authorizationUrl": "https://petstore.swagger.io/oauth/authorize", + "flow": "implicit", + "scopes": { + "read:pets": "read your pets", + "write:pets": "modify pets in your account" + } + } + }, + "definitions": { + "ApiResponse": { + "type": "object", + "properties": { + "code": { + "type": "integer", + "format": "int32" + }, + "type": { + "type": "string" + }, + "message": { + "type": "string" + } + } + }, + "Category": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "name": { + "type": "string" + } + }, + "xml": { + "name": "Category" + } + }, + "Pet": { + "type": "object", + "required": [ + "name", + "photoUrls" + ], + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "category": { + "$ref": "#/definitions/Category" + }, + "name": { + "type": "string", + "example": "doggie" + }, + "photoUrls": { + "type": "array", + "xml": { + "wrapped": true + }, + "items": { + "type": "string", + "xml": { + "name": "photoUrl" + } + } + }, + "tags": { + "type": "array", + "xml": { + "wrapped": true + }, + "items": { + "xml": { + "name": "tag" + }, + "$ref": "#/definitions/Tag" + } + }, + "status": { + "type": "string", + "description": "pet status in the store", + "enum": [ + "available", + "pending", + "sold" + ] + } + }, + "xml": { + "name": "Pet" + } + }, + "Tag": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "name": { + "type": "string" + } + }, + "xml": { + "name": "Tag" + } + }, + "Order": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "petId": { + "type": "integer", + "format": "int64" + }, + "quantity": { + "type": "integer", + "format": "int32" + }, + "shipDate": { + "type": "string", + "format": "date-time" + }, + "status": { + "type": "string", + "description": "Order Status", + "enum": [ + "placed", + "approved", + "delivered" + ] + }, + "complete": { + "type": "boolean" + } + }, + "xml": { + "name": "Order" + } + }, + "User": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "username": { + "type": "string" + }, + "firstName": { + "type": "string" + }, + "lastName": { + "type": "string" + }, + "email": { + "type": "string" + }, + "password": { + "type": "string" + }, + "phone": { + "type": "string" + }, + "userStatus": { + "type": "integer", + "format": "int32", + "description": "User Status" + } + }, + "xml": { + "name": "User" + } + } + }, + "externalDocs": { + "description": "Find out more about Swagger", + "url": "http://swagger.io" + } +} From b490b247f845c8c826128aa15955f251569977e1 Mon Sep 17 00:00:00 2001 From: Ian Roy Sacbibit Date: Tue, 30 Aug 2022 14:26:57 -0400 Subject: [PATCH 09/19] make a new example subfolder --- payment-service/COPYING | 121 ++++++++++ payment-service/LICENSE | 10 + payment-service/README.md | 42 ++++ payment-service/build.sbt | 12 + payment-service/project/build.properties | 1 + payment-service/project/plugins.sbt | 1 + .../sample/become/DiningHakkersOnBecome.scala | 145 ++++++++++++ .../scala/sample/fsm/DiningHakkersOnFsm.scala | 183 ++++++++++++++ .../redelivery/FsmSimpleRedelivery.scala | 223 ++++++++++++++++++ .../sample/typed/DiningHakkersTyped.scala | 208 ++++++++++++++++ 10 files changed, 946 insertions(+) create mode 100644 payment-service/COPYING create mode 100644 payment-service/LICENSE create mode 100644 payment-service/README.md create mode 100644 payment-service/build.sbt create mode 100644 payment-service/project/build.properties create mode 100644 payment-service/project/plugins.sbt create mode 100644 payment-service/src/main/scala/sample/become/DiningHakkersOnBecome.scala create mode 100644 payment-service/src/main/scala/sample/fsm/DiningHakkersOnFsm.scala create mode 100644 payment-service/src/main/scala/sample/redelivery/FsmSimpleRedelivery.scala create mode 100644 payment-service/src/main/scala/sample/typed/DiningHakkersTyped.scala diff --git a/payment-service/COPYING b/payment-service/COPYING new file mode 100644 index 00000000..0e259d42 --- /dev/null +++ b/payment-service/COPYING @@ -0,0 +1,121 @@ +Creative Commons Legal Code + +CC0 1.0 Universal + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS + PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM + THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED + HEREUNDER. + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator +and subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for +the purpose of contributing to a commons of creative, cultural and +scientific works ("Commons") that the public can reliably and without fear +of later claims of infringement build upon, modify, incorporate in other +works, reuse and redistribute as freely as possible in any form whatsoever +and for any purposes, including without limitation commercial purposes. +These owners may contribute to the Commons to promote the ideal of a free +culture and the further production of creative, cultural and scientific +works, or to gain reputation or greater distribution for their Work in +part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any +expectation of additional consideration or compensation, the person +associating CC0 with a Work (the "Affirmer"), to the extent that he or she +is an owner of Copyright and Related Rights in the Work, voluntarily +elects to apply CC0 to the Work and publicly distribute the Work under its +terms, with knowledge of his or her Copyright and Related Rights in the +Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not +limited to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, + communicate, and translate a Work; + ii. moral rights retained by the original author(s) and/or performer(s); +iii. publicity and privacy rights pertaining to a person's image or + likeness depicted in a Work; + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + v. rights protecting the extraction, dissemination, use and reuse of data + in a Work; + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation + thereof, including any amended or successor version of such + directive); and +vii. other similar, equivalent or corresponding rights throughout the + world based on applicable law or treaty, and any national + implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention +of, applicable law, Affirmer hereby overtly, fully, permanently, +irrevocably and unconditionally waives, abandons, and surrenders all of +Affirmer's Copyright and Related Rights and associated claims and causes +of action, whether now known or unknown (including existing as well as +future claims and causes of action), in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or future +medium and for any number of copies, and (iv) for any purpose whatsoever, +including without limitation commercial, advertising or promotional +purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each +member of the public at large and to the detriment of Affirmer's heirs and +successors, fully intending that such Waiver shall not be subject to +revocation, rescission, cancellation, termination, or any other legal or +equitable action to disrupt the quiet enjoyment of the Work by the public +as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason +be judged legally invalid or ineffective under applicable law, then the +Waiver shall be preserved to the maximum extent permitted taking into +account Affirmer's express Statement of Purpose. In addition, to the +extent the Waiver is so judged Affirmer hereby grants to each affected +person a royalty-free, non transferable, non sublicensable, non exclusive, +irrevocable and unconditional license to exercise Affirmer's Copyright and +Related Rights in the Work (i) in all territories worldwide, (ii) for the +maximum duration provided by applicable law or treaty (including future +time extensions), (iii) in any current or future medium and for any number +of copies, and (iv) for any purpose whatsoever, including without +limitation commercial, advertising or promotional purposes (the +"License"). The License shall be deemed effective as of the date CC0 was +applied by Affirmer to the Work. Should any part of the License for any +reason be judged legally invalid or ineffective under applicable law, such +partial invalidity or ineffectiveness shall not invalidate the remainder +of the License, and in such case Affirmer hereby affirms that he or she +will not (i) exercise any of his or her remaining Copyright and Related +Rights in the Work or (ii) assert any associated claims and causes of +action with respect to the Work, in either case contrary to Affirmer's +express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + b. Affirmer offers the Work as-is and makes no representations or + warranties of any kind concerning the Work, express, implied, + statutory or otherwise, including without limitation warranties of + title, merchantability, fitness for a particular purpose, non + infringement, or the absence of latent or other defects, accuracy, or + the present or absence of errors, whether or not discoverable, all to + the greatest extent permissible under applicable law. + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without + limitation any person's Copyright and Related Rights in the Work. + Further, Affirmer disclaims responsibility for obtaining any necessary + consents, permissions or other rights required for any use of the + Work. + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to + this CC0 or use of the Work. diff --git a/payment-service/LICENSE b/payment-service/LICENSE new file mode 100644 index 00000000..4239f09e --- /dev/null +++ b/payment-service/LICENSE @@ -0,0 +1,10 @@ +Akka sample by Lightbend + +Licensed under Public Domain (CC0) + +To the extent possible under law, the person who associated CC0 with +this Template has waived all copyright and related or neighboring +rights to this Template. + +You should have received a copy of the CC0 legalcode along with this +work. If not, see . diff --git a/payment-service/README.md b/payment-service/README.md new file mode 100644 index 00000000..bbd78d62 --- /dev/null +++ b/payment-service/README.md @@ -0,0 +1,42 @@ +## Finite State Machine in Actors + +This sample is an adaptation of [Dining Hakkers](http://www.dalnefre.com/wp/2010/08/dining-philosophers-in-humus/). It illustrates how state and behavior can be managed within an Actor with two different approaches; using `become` and using the `FSM` trait. The sample also contains an implementation of a simple redelivering actor implemented as a FSM. + +## Dining Hakkers with Become + +Open [DiningHakkersOnBecome.scala](src/main/scala/sample/become/DiningHakkersOnBecome.scala). + +It illustrates how current behavior can be replaced with `context.become`. Note that no `var` members are used, instead the state is encoded in the current behavior and its parameters. + +Start the application by typing `sbt "runMain sample.become.DiningHakkersOnBecome"`. In the log output you can see the actions of the `Hakker` actors. + +Read more about `become` in [the documentation](http://doc.akka.io/docs/akka/2.5/scala/actors.html#Become_Unbecome). + +## Dining Hakkers with FSM + +Open [DiningHakkersOnFsm.scala](src/main/scala/sample/fsm/DiningHakkersOnFsm.scala). + +It illustrates how the states and transitions can be defined with the `akka.actor.FSM` trait. + +Start the application by typing `sbt "runMain sample.fsm.DiningHakkersOnFsm"`. In the log output you can see the actions of the `Hakker` actors. + +Read more about `akka.actor.FSM` in [the documentation](http://doc.akka.io/docs/akka/2.5/scala/fsm.html). + +## Simple redelivering FSM + +Open [FsmSimpleRedelivery.scala](src/main/scala/sample/redelivery/FsmSimpleRedelivery.scala). + +It illustrates how you can take care of message redelivery between two or more sides. This implementation is able to process only one message at a time. + +Start the application by typing `sbt "runMain sample.redelivery.FsmSimpleRedelivery"`. In the log output you can see the actions of the `Requester` and the `Receiver` actors. + +## Dining Hakkers with Akka Typed + +Open [DiningHakkersTyped.scala](src/main/scala/sample/typed/DiningHakkersTyped.scala). + +It illustrates how the behaviors and transitions can be defined with Akka Typed. + +Start the application by typing `sbt "runMain sample.typed.DiningHakkersTyped"`. In the log output you can see the actions of the `Hakker` actors. + +Read more about Akka Typed in [the documentation](http://doc.akka.io/docs/akka/current/typed). + diff --git a/payment-service/build.sbt b/payment-service/build.sbt new file mode 100644 index 00000000..6c24310f --- /dev/null +++ b/payment-service/build.sbt @@ -0,0 +1,12 @@ +organization := "com.typesafe.akka.samples" +name := "akka-sample-fsm-scala" + +val akkaVersion = "2.5.17" + +scalaVersion := "2.12.6" +libraryDependencies ++= Seq( + "com.typesafe.akka" %% "akka-actor" % akkaVersion, + "com.typesafe.akka" %% "akka-actor-typed" % akkaVersion +) + +licenses := Seq(("CC0", url("http://creativecommons.org/publicdomain/zero/1.0"))) diff --git a/payment-service/project/build.properties b/payment-service/project/build.properties new file mode 100644 index 00000000..5620cc50 --- /dev/null +++ b/payment-service/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.2.1 diff --git a/payment-service/project/plugins.sbt b/payment-service/project/plugins.sbt new file mode 100644 index 00000000..a7f83b3d --- /dev/null +++ b/payment-service/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("com.dwijnand" % "sbt-dynver" % "3.0.0") diff --git a/payment-service/src/main/scala/sample/become/DiningHakkersOnBecome.scala b/payment-service/src/main/scala/sample/become/DiningHakkersOnBecome.scala new file mode 100644 index 00000000..9e5bc17c --- /dev/null +++ b/payment-service/src/main/scala/sample/become/DiningHakkersOnBecome.scala @@ -0,0 +1,145 @@ +package sample.become + +import akka.actor._ +import scala.concurrent.duration._ + +// Akka adaptation of +// http://www.dalnefre.com/wp/2010/08/dining-philosophers-in-humus/ + +/* +* First we define our messages, they basically speak for themselves +*/ +sealed trait DiningHakkerMessage +final case class Busy(chopstick: ActorRef) extends DiningHakkerMessage +final case class Put(hakker: ActorRef) extends DiningHakkerMessage +final case class Take(hakker: ActorRef) extends DiningHakkerMessage +final case class Taken(chopstick: ActorRef) extends DiningHakkerMessage +object Eat extends DiningHakkerMessage +object Think extends DiningHakkerMessage + +/* +* A Chopstick is an actor, it can be taken, and put back +*/ +class Chopstick extends Actor { + + import context._ + + //When a Chopstick is taken by a hakker + //It will refuse to be taken by other hakkers + //But the owning hakker can put it back + def takenBy(hakker: ActorRef): Receive = { + case Take(otherHakker) => + otherHakker ! Busy(self) + case Put(`hakker`) => + become(available) + } + + //When a Chopstick is available, it can be taken by a hakker + def available: Receive = { + case Take(hakker) => + become(takenBy(hakker)) + hakker ! Taken(self) + } + + //A Chopstick begins its existence as available + def receive = available +} + +/* +* A hakker is an awesome dude or dudette who either thinks about hacking or has to eat ;-) +*/ +class Hakker(name: String, left: ActorRef, right: ActorRef) extends Actor { + + import context._ + + //When a hakker is thinking it can become hungry + //and try to pick up its chopsticks and eat + def thinking: Receive = { + case Eat => + become(hungry) + left ! Take(self) + right ! Take(self) + } + + //When a hakker is hungry it tries to pick up its chopsticks and eat + //When it picks one up, it goes into wait for the other + //If the hakkers first attempt at grabbing a chopstick fails, + //it starts to wait for the response of the other grab + def hungry: Receive = { + case Taken(`left`) => + become(waiting_for(right, left)) + case Taken(`right`) => + become(waiting_for(left, right)) + case Busy(chopstick) => + become(denied_a_chopstick) + } + + //When a hakker is waiting for the last chopstick it can either obtain it + //and start eating, or the other chopstick was busy, and the hakker goes + //back to think about how he should obtain his chopsticks :-) + def waiting_for(chopstickToWaitFor: ActorRef, otherChopstick: ActorRef): Receive = { + case Taken(`chopstickToWaitFor`) => + println("%s has picked up %s and %s and starts to eat".format(name, left.path.name, right.path.name)) + become(eating) + system.scheduler.scheduleOnce(5.seconds, self, Think) + + case Busy(chopstick) => + otherChopstick ! Put(self) + startThinking(10.milliseconds) + } + + //When the results of the other grab comes back, + //he needs to put it back if he got the other one. + //Then go back and think and try to grab the chopsticks again + def denied_a_chopstick: Receive = { + case Taken(chopstick) => + chopstick ! Put(self) + startThinking(10.milliseconds) + case Busy(chopstick) => + startThinking(10.milliseconds) + } + + //When a hakker is eating, he can decide to start to think, + //then he puts down his chopsticks and starts to think + def eating: Receive = { + case Think => + left ! Put(self) + right ! Put(self) + println("%s puts down his chopsticks and starts to think".format(name)) + startThinking(5.seconds) + } + + //All hakkers start in a non-eating state + def receive = { + case Think => + println("%s starts to think".format(name)) + startThinking(5.seconds) + } + + private def startThinking(duration: FiniteDuration): Unit = { + become(thinking) + system.scheduler.scheduleOnce(duration, self, Eat) + } +} + +/* +* Alright, here's our test-harness +*/ +object DiningHakkersOnBecome { + val system = ActorSystem() + + def main(args: Array[String]): Unit = run() + + def run(): Unit = { + //Create 5 chopsticks + val chopsticks = for (i <- 1 to 5) yield system.actorOf(Props[Chopstick], "Chopstick" + i) + + //Create 5 awesome hakkers and assign them their left and right chopstick + val hakkers = for { + (name, i) <- List("Ghosh", "Boner", "Klang", "Krasser", "Manie").zipWithIndex + } yield system.actorOf(Props(classOf[Hakker], name, chopsticks(i), chopsticks((i + 1) % 5))) + + //Signal all hakkers that they should start thinking, and watch the show + hakkers.foreach(_ ! Think) + } +} diff --git a/payment-service/src/main/scala/sample/fsm/DiningHakkersOnFsm.scala b/payment-service/src/main/scala/sample/fsm/DiningHakkersOnFsm.scala new file mode 100644 index 00000000..5df85df0 --- /dev/null +++ b/payment-service/src/main/scala/sample/fsm/DiningHakkersOnFsm.scala @@ -0,0 +1,183 @@ +package sample.fsm + +import akka.actor._ +import akka.actor.FSM._ +import scala.concurrent.duration._ + +// Akka adaptation of +// http://www.dalnefre.com/wp/2010/08/dining-philosophers-in-humus/ + +/* +* Some messages for the chopstick +*/ +sealed trait ChopstickMessage +object Take extends ChopstickMessage +object Put extends ChopstickMessage +final case class Taken(chopstick: ActorRef) extends ChopstickMessage +final case class Busy(chopstick: ActorRef) extends ChopstickMessage + +/** + * Some states the chopstick can be in + */ +sealed trait ChopstickState +case object Available extends ChopstickState +case object Taken extends ChopstickState + +/** + * Some state container for the chopstick + */ +final case class TakenBy(hakker: ActorRef) + +/* +* A chopstick is an actor, it can be taken, and put back +*/ +class Chopstick extends Actor with FSM[ChopstickState, TakenBy] { + import context._ + + // A chopstick begins its existence as available and taken by no one + startWith(Available, TakenBy(system.deadLetters)) + + // When a chopstick is available, it can be taken by a some hakker + when(Available) { + case Event(Take, _) => + goto(Taken) using TakenBy(sender()) replying Taken(self) + } + + // When a chopstick is taken by a hakker + // It will refuse to be taken by other hakkers + // But the owning hakker can put it back + when(Taken) { + case Event(Take, currentState) => + stay replying Busy(self) + case Event(Put, TakenBy(hakker)) if sender() == hakker => + goto(Available) using TakenBy(system.deadLetters) + } + + // Initialize the chopstick + initialize() +} + +/** + * Some fsm hakker messages + */ +sealed trait FSMHakkerMessage +object Think extends FSMHakkerMessage + +/** + * Some fsm hakker states + */ +sealed trait FSMHakkerState +case object Waiting extends FSMHakkerState +case object Thinking extends FSMHakkerState +case object Hungry extends FSMHakkerState +case object WaitForOtherChopstick extends FSMHakkerState +case object FirstChopstickDenied extends FSMHakkerState +case object Eating extends FSMHakkerState + +/** + * Some state container to keep track of which chopsticks we have + */ +final case class TakenChopsticks(left: Option[ActorRef], right: Option[ActorRef]) + +/* +* A fsm hakker is an awesome dude or dudette who either thinks about hacking or has to eat ;-) +*/ +class FSMHakker(name: String, left: ActorRef, right: ActorRef) extends Actor with FSM[FSMHakkerState, TakenChopsticks] { + + //All hakkers start waiting + startWith(Waiting, TakenChopsticks(None, None)) + + when(Waiting) { + case Event(Think, _) => + println("%s starts to think".format(name)) + startThinking(5.seconds) + } + + //When a hakker is thinking it can become hungry + //and try to pick up its chopsticks and eat + when(Thinking) { + case Event(StateTimeout, _) => + left ! Take + right ! Take + goto(Hungry) + } + + // When a hakker is hungry it tries to pick up its chopsticks and eat + // When it picks one up, it goes into wait for the other + // If the hakkers first attempt at grabbing a chopstick fails, + // it starts to wait for the response of the other grab + when(Hungry) { + case Event(Taken(`left`), _) => + goto(WaitForOtherChopstick) using TakenChopsticks(Some(left), None) + case Event(Taken(`right`), _) => + goto(WaitForOtherChopstick) using TakenChopsticks(None, Some(right)) + case Event(Busy(_), _) => + goto(FirstChopstickDenied) + } + + // When a hakker is waiting for the last chopstick it can either obtain it + // and start eating, or the other chopstick was busy, and the hakker goes + // back to think about how he should obtain his chopsticks :-) + when(WaitForOtherChopstick) { + case Event(Taken(`left`), TakenChopsticks(None, Some(right))) => startEating(left, right) + case Event(Taken(`right`), TakenChopsticks(Some(left), None)) => startEating(left, right) + case Event(Busy(chopstick), TakenChopsticks(leftOption, rightOption)) => + leftOption.foreach(_ ! Put) + rightOption.foreach(_ ! Put) + startThinking(10.milliseconds) + } + + private def startEating(left: ActorRef, right: ActorRef): State = { + println("%s has picked up %s and %s and starts to eat".format(name, left.path.name, right.path.name)) + goto(Eating) using TakenChopsticks(Some(left), Some(right)) forMax (5.seconds) + } + + // When the results of the other grab comes back, + // he needs to put it back if he got the other one. + // Then go back and think and try to grab the chopsticks again + when(FirstChopstickDenied) { + case Event(Taken(secondChopstick), _) => + secondChopstick ! Put + startThinking(10.milliseconds) + case Event(Busy(chopstick), _) => + startThinking(10.milliseconds) + } + + // When a hakker is eating, he can decide to start to think, + // then he puts down his chopsticks and starts to think + when(Eating) { + case Event(StateTimeout, _) => + println("%s puts down his chopsticks and starts to think".format(name)) + left ! Put + right ! Put + startThinking(5.seconds) + } + + // Initialize the hakker + initialize() + + private def startThinking(duration: FiniteDuration): State = { + goto(Thinking) using TakenChopsticks(None, None) forMax duration + } +} + +/* +* Alright, here's our test-harness +*/ +object DiningHakkersOnFsm { + + val system = ActorSystem() + + def main(args: Array[String]): Unit = run() + + def run(): Unit = { + // Create 5 chopsticks + val chopsticks = for (i <- 1 to 5) yield system.actorOf(Props[Chopstick], "Chopstick" + i) + // Create 5 awesome fsm hakkers and assign them their left and right chopstick + val hakkers = for { + (name, i) <- List("Ghosh", "Boner", "Klang", "Krasser", "Manie").zipWithIndex + } yield system.actorOf(Props(classOf[FSMHakker], name, chopsticks(i), chopsticks((i + 1) % 5))) + + hakkers.foreach(_ ! Think) + } +} diff --git a/payment-service/src/main/scala/sample/redelivery/FsmSimpleRedelivery.scala b/payment-service/src/main/scala/sample/redelivery/FsmSimpleRedelivery.scala new file mode 100644 index 00000000..56dca971 --- /dev/null +++ b/payment-service/src/main/scala/sample/redelivery/FsmSimpleRedelivery.scala @@ -0,0 +1,223 @@ +/** + * Copyright (C) 2009-2016 Lightbend Inc. + */ + +package sample.redelivery + +import akka.actor._ +import scala.concurrent.duration._ +import java.util.concurrent.ThreadLocalRandom +import java.util.UUID + +object SimpleOrderedRedeliverer { + /** + * Props for creating a [[SimpleOrderedRedeliverer]]. + */ + def props(retryTimeout: FiniteDuration) = Props(classOf[SimpleOrderedRedeliverer], retryTimeout) + + /* + * Messages exchanged with the requester of the delivery. + */ + case class Deliver(to: ActorRef, msg: Any, uuid: UUID) + case class Delivered(uuid: UUID) + case class AcceptedForDelivery(uuid: UUID) + case class Busy(refused: UUID, currentlyProcessing: UUID) + + /* + * Messages exchanged with the “deliveree”. + */ + case class Ackable(from: ActorRef, msg: Any, uuid: UUID) + case class Ack(uuid: UUID) + + /* + * Various states the [[SimpleOrderedRedeliverer]] can be in. + */ + sealed trait State + case object Idle extends State + case object AwaitingAck extends State + + sealed trait Data + case object NoData extends Data + + /** + * Keeps track of our last delivery request. + */ + case class LastRequest(last: Deliver, requester: ActorRef) extends Data + + /** + * Private message used only inside of the [[SimpleOrderedRedeliverer]] to signalize a tick of its retry timer. + */ + private case object Retry +} + +/** + * An actor-in-the-middle kind. Takes care of message redelivery between two or more sides. + * + * Works “sequentially”, thus is able to process only one message at a time: + * + *
+ *   Delivery-request#1 -> ACK#1 -> Delivery-request#2 -> ACK#2 -> ...
+ * 
+ * + * A situation like this: + * + *
+ *   Delivery-request#1 -> Delivery-request#2 -> ...
+ * 
+ * + * ... will result in the second requester getting a [[SimpleOrderedRedeliverer.Busy]] message with [[UUID]]s + * of both his request and currently-processed one. + * + * @param retryTimeout how long to wait for the [[SimpleOrderedRedeliverer.Ack]] message + */ +class SimpleOrderedRedeliverer(retryTimeout: FiniteDuration) extends Actor with FSM[SimpleOrderedRedeliverer.State, SimpleOrderedRedeliverer.Data] { + import SimpleOrderedRedeliverer._ + + // So that we don't make a typo when referencing this timer. + val RetryTimer = "retry" + + // Start idle with neither last request, nor most recent requester. + startWith(Idle, NoData) + + /** + * Will process the provided request, sending an [[Ackable]] to its recipient and resetting the inner timer. + * @return a new post-processing state. + */ + def process(request: Deliver, requester: ActorRef): State = { + request.to ! Ackable(requester, request.msg, request.uuid) + setTimer(RetryTimer, Retry, retryTimeout, repeat = false) + goto(AwaitingAck) using LastRequest(request, requester) + } + + /* + * When [[Idle]], accept new requests and process them, replying with [[WillTry]]. + */ + when(Idle) { + case Event(request: Deliver, _) => + process(request, sender()) replying AcceptedForDelivery(request.uuid) + } + + when(AwaitingAck) { + + /* + * When awaiting the [[Ack]] and receiver seems not to have made it, + * resend the message wrapped in [[Ackable]]. This time, however, without + * sending [[WillTry]] to our requester! + */ + case Event(Retry, LastRequest(request, requester)) => + process(request, requester) + + /* + * Fortunately, the receiver made it! It his is an [[Ack]] of correct [[UUID]], + * cancel the retry timer, notify original requester with [[Delivered]] message, + * and turn [[Idle]] again. + */ + case Event(Ack(uuid), LastRequest(request, requester)) if uuid == request.uuid => + cancelTimer(RetryTimer) + requester ! Delivered(uuid) + goto(Idle) using NoData + + /* + * Someone (possibly else!) is trying to make the [[SimpleOrderedRedeliverer]] deliver a new message, + * while an [[Ack]] for the last one has not yet been delivered. Reject. + */ + case Event(request: Deliver, LastRequest(current, _)) => + stay() replying Busy(request.uuid, current.uuid) + } + +} + +object Receiver { + /** + * Props for creating a [[Receiver]]. + */ + def props = Props(classOf[Receiver]) +} + +class Receiver extends Actor { + /** + * Simulate losing 75% of all messages on the receiving end. We want to see the redelivery in action! + */ + def shouldSendAck = ThreadLocalRandom.current.nextDouble() < 0.25 + + def receive = { + case SimpleOrderedRedeliverer.Ackable(from, msg, uuid) => + val goingToSendAck = shouldSendAck + println(s""" [Receiver] got "$msg"; ${if (goingToSendAck) "" else " ***NOT***"} going to send Ack this time""") + // Send a [[SimpleOrderedRedeliverer.Ack]] -- if they're lucky! + if (goingToSendAck) sender() ! SimpleOrderedRedeliverer.Ack(uuid) + } +} + +object Requester { + /** + * Props for creating a [[Requester]]. + */ + def props = Props(classOf[Requester]) + + /** + * Requester-private message used to drive the simulation. + */ + private case object Tick +} + +class Requester extends Actor { + import Requester._ + import context.dispatcher + + /* + * Create a [[SimpleOrderedRedeliverer]] and a [[Receiver]]. + */ + val redeliverer = context.actorOf(SimpleOrderedRedeliverer.props(retryTimeout = 3.seconds)) + val receiver = context.actorOf(Receiver.props) + + /* + * One message would be quite boring, let's pick a random of the three! + */ + val messages = List("Hello!", "Ping!", "Howdy!") + + /* + * Start ticking! + */ + self ! Tick + + /** + * Make a new request every anywhere-between-1-and-10 seconds. + */ + def nextTickIn: FiniteDuration = (1.0 + ThreadLocalRandom.current.nextDouble() * 9.0).seconds + + def receive = { + case Tick => + val msg = util.Random.shuffle(messages).head + val uuid = UUID.randomUUID() + println(s"""[Requester] requesting ("$msg", $uuid) to be sent to [Receiver]...""") + + /* + * Make the actual request... + */ + redeliverer ! SimpleOrderedRedeliverer.Deliver(receiver, msg, uuid) + + /* + * ... and schedule a new [[Tick]]. + */ + context.system.scheduler.scheduleOnce(nextTickIn, self, Tick) + + /* + * This case is used for displaying [[SimpleOrderedRedeliverer.WillTry]] and [[SimpleOrderedRedeliverer.Delivered]] + * and [[SimpleOrderedRedeliverer.Busy]] messages. + */ + case msg => println(s"[Requester] got $msg") + } + +} + +object FsmSimpleRedelivery extends App { + + val system = ActorSystem() + + /* + * Start a new [[Requester]] actor. + */ + system.actorOf(Requester.props) + +} diff --git a/payment-service/src/main/scala/sample/typed/DiningHakkersTyped.scala b/payment-service/src/main/scala/sample/typed/DiningHakkersTyped.scala new file mode 100644 index 00000000..8ac88089 --- /dev/null +++ b/payment-service/src/main/scala/sample/typed/DiningHakkersTyped.scala @@ -0,0 +1,208 @@ +package sample.typed + +import akka.NotUsed +import akka.actor.typed.scaladsl.{ActorContext, Behaviors} +import akka.actor.typed.{ActorRef, ActorSystem, Behavior} + +import scala.concurrent.duration._ + +// Akka adaptation of +// http://www.dalnefre.com/wp/2010/08/dining-philosophers-in-humus/ + +/* +* Some messages for the chopstick +*/ +sealed trait ChopstickMessage +final case class Take(ref: ActorRef[ChopstickAnswer]) extends ChopstickMessage +final case class Put(ref: ActorRef[ChopstickAnswer]) extends ChopstickMessage + +sealed trait ChopstickAnswer +final case class Taken(chopstick: ActorRef[ChopstickMessage]) extends ChopstickAnswer +final case class Busy(chopstick: ActorRef[ChopstickMessage]) extends ChopstickAnswer + +/* +* A Chopstick is an actor, it can be taken, and put back +*/ +object Chopstick { + + //When a Chopstick is taken by a hakker + //It will refuse to be taken by other hakkers + //But the owning hakker can put it back + def takenBy(hakker: ActorRef[ChopstickAnswer]): Behavior[ChopstickMessage] = { + Behaviors.receive { + case (ctx, Take(otherHakker)) => + otherHakker ! Busy(ctx.self) + Behaviors.same + case (ctx, Put(`hakker`)) => + available + case _ => + // here and below it's left to be explicit about partial definition, + // but can be omitted when Behaviors.receivePartial is in use + Behaviors.unhandled + } + } + + //When a Chopstick is available, it can be taken by a hakker + lazy val available: Behavior[ChopstickMessage] = { + Behaviors.receive { + case (ctx, Take(hakker)) => + hakker ! Taken(ctx.self) + takenBy(hakker) + case _ => + Behaviors.unhandled + } + } +} + +/** + * Some fsm hakker messages + */ +sealed trait HakkerMessage +case object Think extends HakkerMessage +case object Eat extends HakkerMessage + +/* +* A hakker is an awesome dude or dudette who either thinks about hacking or has to eat ;-) +*/ +class Hakker(name: String, left: ActorRef[ChopstickMessage], right: ActorRef[ChopstickMessage]) { + + final case class ChopstickAnswerAdaptor(msg: ChopstickAnswer) extends HakkerMessage + + lazy val waiting: Behavior[HakkerMessage] = + Behaviors.receive { + case (ctx, Think) => + println(s"$name starts to think") + startThinking(ctx, 5.seconds) + case _ => + Behaviors.unhandled + } + + //When a hakker is thinking it can become hungry + //and try to pick up its chopsticks and eat + lazy val thinking: Behavior[HakkerMessage] = + Behaviors.setup { ctx => + val adapter = ctx.messageAdapter(ChopstickAnswerAdaptor) + Behaviors.receiveMessage { + case Eat => + left ! Take(adapter) + right ! Take(adapter) + hungry + case _ => + Behaviors.unhandled + } + } + + //When a hakker is hungry it tries to pick up its chopsticks and eat + //When it picks one up, it goes into wait for the other + //If the hakkers first attempt at grabbing a chopstick fails, + //it starts to wait for the response of the other grab + lazy val hungry: Behavior[HakkerMessage] = + Behaviors.receiveMessage { + case ChopstickAnswerAdaptor(Taken(`left`)) => + waitForOtherChopstick(chopstickToWaitFor = right, takenChopstick = left) + + case ChopstickAnswerAdaptor(Taken(`right`)) => + waitForOtherChopstick(chopstickToWaitFor = left, takenChopstick = right) + + case ChopstickAnswerAdaptor(Busy(chopstick)) => + firstChopstickDenied + case _ => + Behaviors.unhandled + } + + //When a hakker is waiting for the last chopstick it can either obtain it + //and start eating, or the other chopstick was busy, and the hakker goes + //back to think about how he should obtain his chopsticks :-) + def waitForOtherChopstick(chopstickToWaitFor: ActorRef[ChopstickMessage], + takenChopstick: ActorRef[ChopstickMessage]): Behavior[HakkerMessage] = + + Behaviors.setup { ctx => + val adapter = ctx.messageAdapter(ChopstickAnswerAdaptor) + Behaviors.receiveMessage { + case ChopstickAnswerAdaptor(Taken(`chopstickToWaitFor`)) => + println(s"$name has picked up ${left.path.name} and ${right.path.name} and starts to eat") + startEating(ctx, 5.seconds) + + case ChopstickAnswerAdaptor(Busy(`chopstickToWaitFor`)) => + takenChopstick ! Put(adapter) + startThinking(ctx, 10.milliseconds) + case _ => + Behaviors.unhandled + } + } + + //When a hakker is eating, he can decide to start to think, + //then he puts down his chopsticks and starts to think + lazy val eating: Behavior[HakkerMessage] = + Behaviors.setup { ctx => + val adapter = ctx.messageAdapter(ChopstickAnswerAdaptor) + Behaviors.receiveMessage { + case Think => + println(s"$name puts down his chopsticks and starts to think") + left ! Put(adapter) + right ! Put(adapter) + startThinking(ctx, 5.seconds) + case _ => + Behaviors.unhandled + } + } + + //When the results of the other grab comes back, + //he needs to put it back if he got the other one. + //Then go back and think and try to grab the chopsticks again + lazy val firstChopstickDenied: Behavior[HakkerMessage] = + Behaviors.setup { ctx => + val adapter = ctx.messageAdapter(ChopstickAnswerAdaptor) + Behaviors.receiveMessage { + case ChopstickAnswerAdaptor(Taken(chopstick)) => + chopstick ! Put(adapter) + startThinking(ctx, 10.milliseconds) + case ChopstickAnswerAdaptor(Busy(_)) => + startThinking(ctx, 10.milliseconds) + case _ => + Behaviors.unhandled + } + } + + private def startThinking(ctx: ActorContext[HakkerMessage], duration: FiniteDuration) = { + Behaviors.withTimers[HakkerMessage] { timers => + timers.startSingleTimer(Eat, Eat, duration) + thinking + } + } + + private def startEating(ctx: ActorContext[HakkerMessage], duration: FiniteDuration) = { + Behaviors.withTimers[HakkerMessage] { timers => + timers.startSingleTimer(Think, Think, duration) + eating + } + } +} + + +/* +* Alright, here's our test-harness +*/ +object DiningHakkersTyped { + + def mainBehavior: Behavior[NotUsed] = Behaviors.setup { context => + + //Create 5 chopsticks + val chopsticks = for (i <- 1 to 5) yield context.spawn(Chopstick.available, "Chopstick" + i) + + //Create 5 awesome hakkers and assign them their left and right chopstick + val hakkers = for { + (name, i) <- List("Ghosh", "Boner", "Klang", "Krasser", "Manie").zipWithIndex + } yield context.spawn(new Hakker(name, chopsticks(i), chopsticks((i + 1) % 5)).waiting, name) + + //Signal all hakkers that they should start thinking, and watch the show + hakkers.foreach(_ ! Think) + + Behaviors.empty + } + + def main(args: Array[String]): Unit = { + ActorSystem(mainBehavior, "DinningHakkers") + } +} + From 6a6a956ba0b62c5fe500eabeeeab074bb8f112b4 Mon Sep 17 00:00:00 2001 From: Ian Roy Sacbibit Date: Tue, 30 Aug 2022 14:30:03 -0400 Subject: [PATCH 10/19] add opslevel.yml --- payment-service/opslevel.yml | 43 ++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 payment-service/opslevel.yml diff --git a/payment-service/opslevel.yml b/payment-service/opslevel.yml new file mode 100644 index 00000000..3e6377e9 --- /dev/null +++ b/payment-service/opslevel.yml @@ -0,0 +1,43 @@ +--- +version: 1 +service: + name: Payment Service + lifecycle: generally_available + tier: tier_4 + product: Payment + owner: inventory_team + language: Ruby + framework: Sinatra + description: Manages payments. + aliases: + tags: + tools: + - name: Kubernetes + category: orchestrator + url: https://deploy.gandalfsbooks.com/payment-service + environment: + - name: Sentry + category: errors + url: https://gandalfsbooks.sentry.com/payment-service + environment: + - name: Pingdom + category: health_checks + url: https://gandalfsbooks.pingdom.com/payment-service + environment: + - name: Splunk + category: logs + url: https://logs.gandalfsbooks.com/payment-service + environment: + - name: GitHub + category: code + url: https://github.com/gandalfsbooks/scala-monorepo/tree/2.5/payment-service + environment: + - name: LaunchDarkly + category: feature_flag + url: https://launchdarkly.com/foo + environment: + - name: Issue Tracking + category: issue_tracking + url: https://gandalfsbooks.atlassian.net/jira/software/c/projects/BE/boards/1 + environment: + dependencies: From 6d178057f7be752a0d4b48ca0f5e3835da0b454c Mon Sep 17 00:00:00 2001 From: Ian Roy Sacbibit Date: Tue, 30 Aug 2022 14:31:12 -0400 Subject: [PATCH 11/19] delete opslevel.yml --- payment-service/opslevel.yml | 43 ------------------------------------ 1 file changed, 43 deletions(-) delete mode 100644 payment-service/opslevel.yml diff --git a/payment-service/opslevel.yml b/payment-service/opslevel.yml deleted file mode 100644 index 3e6377e9..00000000 --- a/payment-service/opslevel.yml +++ /dev/null @@ -1,43 +0,0 @@ ---- -version: 1 -service: - name: Payment Service - lifecycle: generally_available - tier: tier_4 - product: Payment - owner: inventory_team - language: Ruby - framework: Sinatra - description: Manages payments. - aliases: - tags: - tools: - - name: Kubernetes - category: orchestrator - url: https://deploy.gandalfsbooks.com/payment-service - environment: - - name: Sentry - category: errors - url: https://gandalfsbooks.sentry.com/payment-service - environment: - - name: Pingdom - category: health_checks - url: https://gandalfsbooks.pingdom.com/payment-service - environment: - - name: Splunk - category: logs - url: https://logs.gandalfsbooks.com/payment-service - environment: - - name: GitHub - category: code - url: https://github.com/gandalfsbooks/scala-monorepo/tree/2.5/payment-service - environment: - - name: LaunchDarkly - category: feature_flag - url: https://launchdarkly.com/foo - environment: - - name: Issue Tracking - category: issue_tracking - url: https://gandalfsbooks.atlassian.net/jira/software/c/projects/BE/boards/1 - environment: - dependencies: From a1e6da9ca40940b721f30ee3cf384a1e77362898 Mon Sep 17 00:00:00 2001 From: Ian Roy Sacbibit Date: Tue, 30 Aug 2022 16:11:43 -0400 Subject: [PATCH 12/19] add opslevel.yml to subfolder --- payment-service/opslevel.yml | 43 ++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 payment-service/opslevel.yml diff --git a/payment-service/opslevel.yml b/payment-service/opslevel.yml new file mode 100644 index 00000000..3e6377e9 --- /dev/null +++ b/payment-service/opslevel.yml @@ -0,0 +1,43 @@ +--- +version: 1 +service: + name: Payment Service + lifecycle: generally_available + tier: tier_4 + product: Payment + owner: inventory_team + language: Ruby + framework: Sinatra + description: Manages payments. + aliases: + tags: + tools: + - name: Kubernetes + category: orchestrator + url: https://deploy.gandalfsbooks.com/payment-service + environment: + - name: Sentry + category: errors + url: https://gandalfsbooks.sentry.com/payment-service + environment: + - name: Pingdom + category: health_checks + url: https://gandalfsbooks.pingdom.com/payment-service + environment: + - name: Splunk + category: logs + url: https://logs.gandalfsbooks.com/payment-service + environment: + - name: GitHub + category: code + url: https://github.com/gandalfsbooks/scala-monorepo/tree/2.5/payment-service + environment: + - name: LaunchDarkly + category: feature_flag + url: https://launchdarkly.com/foo + environment: + - name: Issue Tracking + category: issue_tracking + url: https://gandalfsbooks.atlassian.net/jira/software/c/projects/BE/boards/1 + environment: + dependencies: From a670fd09826ae829bf9f7b02103662c27d84bc4d Mon Sep 17 00:00:00 2001 From: ianroydemo <96147516+ianroydemo@users.noreply.github.com> Date: Tue, 6 Sep 2022 09:58:42 -0400 Subject: [PATCH 13/19] Rename opslevel.yml to opslevel.yml.old --- payment-service/{opslevel.yml => opslevel.yml.old} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename payment-service/{opslevel.yml => opslevel.yml.old} (100%) diff --git a/payment-service/opslevel.yml b/payment-service/opslevel.yml.old similarity index 100% rename from payment-service/opslevel.yml rename to payment-service/opslevel.yml.old From 941c8bf39d0b924f97d5730916dcb37d89f3b978 Mon Sep 17 00:00:00 2001 From: ianroydemo <96147516+ianroydemo@users.noreply.github.com> Date: Tue, 6 Sep 2022 14:20:37 -0400 Subject: [PATCH 14/19] Rename opslevel.yml.old to opslevel.yml --- payment-service/{opslevel.yml.old => opslevel.yml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename payment-service/{opslevel.yml.old => opslevel.yml} (100%) diff --git a/payment-service/opslevel.yml.old b/payment-service/opslevel.yml similarity index 100% rename from payment-service/opslevel.yml.old rename to payment-service/opslevel.yml From 36cfdc8cd77aefe7e3babaf2206719fe6f2e8a60 Mon Sep 17 00:00:00 2001 From: ianroydemo <96147516+ianroydemo@users.noreply.github.com> Date: Tue, 25 Apr 2023 11:28:24 -0400 Subject: [PATCH 15/19] Update opslevel.yml --- payment-service/opslevel.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/payment-service/opslevel.yml b/payment-service/opslevel.yml index 3e6377e9..8911ed83 100644 --- a/payment-service/opslevel.yml +++ b/payment-service/opslevel.yml @@ -5,7 +5,7 @@ service: lifecycle: generally_available tier: tier_4 product: Payment - owner: inventory_team + owner: transactions_team language: Ruby framework: Sinatra description: Manages payments. From a541972c83dd48d1eb436fda4342c2f791c5a542 Mon Sep 17 00:00:00 2001 From: ianroydemo <96147516+ianroydemo@users.noreply.github.com> Date: Tue, 25 Apr 2023 11:58:54 -0400 Subject: [PATCH 16/19] Create CODEOWNERS --- catalog-service/CODEOWNERS | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 catalog-service/CODEOWNERS diff --git a/catalog-service/CODEOWNERS b/catalog-service/CODEOWNERS new file mode 100644 index 00000000..57ab15fa --- /dev/null +++ b/catalog-service/CODEOWNERS @@ -0,0 +1,8 @@ +# file/directory user +# + +*.rb @toddg-opslevel + +app/ @ecohen-opslevel + +components/*.md @ianroys-opslevel From d12c77d4dca9dd26ee3af128a55cbc03a4661fdd Mon Sep 17 00:00:00 2001 From: ianroydemo <96147516+ianroydemo@users.noreply.github.com> Date: Wed, 17 May 2023 16:16:05 -0400 Subject: [PATCH 17/19] Update opslevel.yml --- payment-service/opslevel.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/payment-service/opslevel.yml b/payment-service/opslevel.yml index 8911ed83..bfde1a0e 100644 --- a/payment-service/opslevel.yml +++ b/payment-service/opslevel.yml @@ -6,6 +6,7 @@ service: tier: tier_4 product: Payment owner: transactions_team + system: cart language: Ruby framework: Sinatra description: Manages payments. From 214e536e310de868b7a225a4ab3a3db19ad07559 Mon Sep 17 00:00:00 2001 From: ianroydemo <96147516+ianroydemo@users.noreply.github.com> Date: Wed, 17 May 2023 16:28:53 -0400 Subject: [PATCH 18/19] Update opslevel.yml --- payment-service/opslevel.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/payment-service/opslevel.yml b/payment-service/opslevel.yml index bfde1a0e..afdc9df4 100644 --- a/payment-service/opslevel.yml +++ b/payment-service/opslevel.yml @@ -6,7 +6,7 @@ service: tier: tier_4 product: Payment owner: transactions_team - system: cart + system: support language: Ruby framework: Sinatra description: Manages payments. From 2df7a091b814750bbc0755b369fdcca8af027e52 Mon Sep 17 00:00:00 2001 From: ianroydemo <96147516+ianroydemo@users.noreply.github.com> Date: Wed, 17 May 2023 16:29:09 -0400 Subject: [PATCH 19/19] Update opslevel.yml --- payment-service/opslevel.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/payment-service/opslevel.yml b/payment-service/opslevel.yml index afdc9df4..bfde1a0e 100644 --- a/payment-service/opslevel.yml +++ b/payment-service/opslevel.yml @@ -6,7 +6,7 @@ service: tier: tier_4 product: Payment owner: transactions_team - system: support + system: cart language: Ruby framework: Sinatra description: Manages payments.