A simple pet store service implemented as a Datomic Ion using the pedestal.ions chain provider. Consumes and emits JSON and supports CRUD operation on Pet resources.
Demonstrates:
- Ionizing a Pedestal service.
- Using Ion Parameters.
- Transacting schema.
- Running the service locally via Jetty.
- You have an AWS account with sufficient privileges which you can use to provision Datomic Cloud. If you don't have an AWS account, refer to the AWS documentation for instructions on how to set one up. Note: Running this sample will incur AWS charges. The cost of running Datomic Cloud's Solo topology is approximately $1/day.
- You have AWS credentials provisioned locally. Refer to the AWS documentation for details on how to set up credentials.
Follow the Datomic Cloud Setting Up
guide to provision your Datomic Cloud environment. Be sure to choose
the Solo Fulfillment option. This sample assumes the _Stack Name
is ion-pet-service
.
Once your Datomic Cloud environment is provisioned, continue on to the Configuring Access documentation and, finally, the Getting Started guide.
You will need to export the following environment variables in order to run this sample locally:
AWS_PROFILE
: The AWS profile in your AWS credentials file.AWS_REGION
: The AWS region in which you have provisioned Datomic Cloud.DATOMIC_ENV_MAP
: See below.DATOMIC_APP_INFO_MAP
: See below.
The Datomic Ion param environment variables should be set as follows:
export DATOMIC_ENV_MAP="{:env :dev}""
export DATOMIC_APP_INFO_MAP="{:app-name \"ion-pet-service\" :deployment-group \"$DeploymentGroup\"}"
Where $DeploymentGroup
is the name of your Ion deployment group (see
Ion Deploy).
Pedestal Ions provides access to Datomic Ion parameters. Refer to the README for details.
The values of the :io.pedestal.ions/app-info
and
:io.pedestal.ions/env-map
keys are pulled from their
respective Datomic Ion param environment variables which were
specified in the Local Development
section of this guide.
To run this sample, you will need to create a db-name
parameter in AWS Systems
Manager Parameter Store. This can be done as follows:
aws ssm put-parameter --name /datomic-shared/dev/ion-pet-service/db-name --value pet-store --type String
To push the project to your Datomic Cloud environment, execute the following command from the root directory of the sample project:
clojure -A:dev -m datomic.ion.dev '{:op :push"}'
You will need to add a :uname
key if you have made changes to the
sample and they have not been committed to Git.
This command will return a map containing the key
:deploy-command
. Copy the value and execute it at the command line
to deploy the ionized app. You will need to unescape the :uname
value.
The deployment command returns a map as well. This map contains the
key :status-command
. Copy the value of this key and execute it on
the command line to track the status of the deployment. After a few
seconds you should see a successful result that looks like this:
{:deploy-status "SUCCEEDED", :code-deploy-status "SUCCEEDED"}
- Go to the AWS API Gateway console to create a new AWS API Gateway for this sample.
- Choose New API from the Create new API options.
- Name your API pet-service.
- Click Create API.
- Under the Actions dropdown, choose Create Resource.
- Check the box Configure as proxy resource.
- Click Create Resource.
To connect the API to the deployed pet service ion:
- Select the ANY method under
/{proxy+}
. - Leave the Integration type as Lambda Function Proxy.
- Set the Lambda Function to
ion-pet-service-${Group}-app
, where$Group
is your Datomic Cloud compute group. - Click Save.
- Choose Ok to give your API Gateway permission to call your lambda.
- Under your API in the left side of the UI, click on the bottom choice Settings.
- Choose Add Binary Media Type, add the
*/*
type. - Click Save Changes.
To deploy your API:
- Click on your API name and choose Deploy API under the Actions dropdown.
- Choose New Stage as the Deployment Stage, add the stage
dev
, then choose Deploy.
The top of the Stage Editor will show the url for your app.
Your API is now deployed. Keep in mind that it is public. Be sure to remove it when done using it!
The commands that follow expect that you replace $INVOKE_URL
with
the Invoke URL of your deployed api.
curl -X GET https://$INVOKE_URL/dev/pets
You should see the following result:
[
{
"pet-store.pet/id": 2,
"pet-store.pet/name": "Dante",
"pet-store.pet/tag": "cat"
},
{
"pet-store.pet/id": 1,
"pet-store.pet/name": "Yogi",
"pet-store.pet/tag": "dog"
}
]
curl -X POST \
https://$INVOKE_URL/dev/pets \
-H 'Cache-Control: no-cache' \
-H 'Content-Type: application/json' \
-d ' {
"id": 302,
"name": "Foobar",
"tag": "bird"
}'
Which should return a 201: Created
.
Perform another GET
of /pets
will include the new pet.
curl -X GET https://$INVOKE_URL/dev/pets
[
{
"pet-store.pet/id": 2,
"pet-store.pet/name": "Dante",
"pet-store.pet/tag": "cat"
},
{
"pet-store.pet/id": 302,
"pet-store.pet/name": "Foobar",
"pet-store.pet/tag": "bird"
},
{
"pet-store.pet/id": 1,
"pet-store.pet/name": "Yogi",
"pet-store.pet/tag": "dog"
}
]
Update the petFoobar
:
curl -X PUT \
https://$INVOKE_URL/dev/pet/302 \
-H 'Cache-Control: no-cache' \
-H 'Content-Type: application/json' \
-d ' {
"name": "Foox",
"tag": "bird"
}'
The updated pet will be returned:
{
"pet-store.pet/id": 302,
"pet-store.pet/name": "Foox",
"pet-store.pet/tag": "Bird"
}
Now remove the pet Foox
:
curl -X DELETE \
https://$INVOKE_URL/dev/pet/302 \
-H 'Cache-Control: no-cache'
A response with the HTTP status 204: No content
will be returned.
Start the SOCKS proxy as per the Datomic Cloud docs.
Start a repl and connect to it:
$ clj -Adev:log
Instantiate a handler so you can interact with the app:
user=> (require '[ion-provider.ion :as ion]
'[ion-provider.service :as service])
user=> (def h (ion/handler service/service))
Make some requests:
user=> (h {:server-port 0
:server-name "localhost"
:remote-addr "127.0.0.1"
:uri "/"
:scheme "http"
:request-method :get
:headers {}})
INFO io.pedestal.http - {:msg "GET /", :line 80}
{:status 200, :headers {"Strict-Transport-Security" "max-age=31536000; includeSubdomains", "X-Frame-Options" "DENY", "X-Content-Type-Options" "nosniff", "X-XSS-Protection" "1; mode=block", "X-Download-Options" "noopen", "X-Permitted-Cross-Domain-Policies" "none", "Content-Security-Policy" "object-src 'none'; script-src 'unsafe-inline' 'unsafe-eval' 'strict-dynamic' https: http:;", "Content-Type" "text/plain"}, :body "Hello World!"}
user=> (slurp (:body (h {:server-port 0
:server-name "localhost"
:remote-addr "127.0.0.1"
:uri "/pets"
:scheme "http"
:request-method :get})))
INFO io.pedestal.http - {:msg "GET /pets", :line 80}
...
"[{\"pet-store.pet/id\":2,\"pet-store.pet/name\":\"Dante\",\"pet-store.pet/tag\":\"cat\"},{\"pet-store.pet/id\":1,\"pet-store.pet/name\":\"Yogi\",\"pet-store.pet/tag\":\"dog\"}]"
You may prefer interacting with a locally running service instead of
the ion handler. You can do so by configuring the service to use jetty
instead of the ion chain provider. The ion-sample.server
namespace demonstrates this. Keep in mind that you still need to have
the Datomic SOCKS proxy running to access Datomic Cloud!
The ion-sample.server
source is found in the dev
source
directory. To include it and the pedestal.jetty
dependency, start up
a repl with the :jetty
alias appended as follows:
$ clj -Adev:log:jetty
Then startup a server:
user=> (require '[ion-sample.server :as server])
user=> (def pet-service (server/run-dev 9091))
You can now interact with your server via curl
:
$ curl -X GET http://localhost:9091/pets
which returns:
[{"pet-store.pet/id":2,"pet-store.pet/name":"Dante","pet-store.pet/tag":"cat"},{"pet-store.pet/id":1,"pet-store.pet/name":"Yogi","pet-store.pet/tag":"dog"}]%
Once you are done interacting with the service, you can stop it as follows:
$ (server/stop pet-service)
Follow the Datomic Cloud Deleting a System guide for instructions on removing the provisioned resources.
Delete the policy Datomic-ion-pet-service-{REGION}
Delete the CodeDeploy project ion-pet-service
.
Copyright 2018 Cognitect, Inc.
The use and distribution terms for this software are covered by the Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0) which can be found in the file epl-v10.html at the root of this distribution.
By using this software in any fashion, you are agreeing to be bound by the terms of this license.
You must not remove this notice, or any other, from this software.