Add an install guide

This commit is contained in:
Vikram Rangnekar 2019-04-13 09:12:41 -04:00
parent dd3132bda0
commit 5bd2f5a339
3 changed files with 167 additions and 49 deletions

View File

@ -38,7 +38,12 @@ open http://localhost:3000
open http://localhost:8080 open http://localhost:8080
``` ```
## Try this GraphQL query ::: warning DEMO REQUIREMENTS
This demo requires `docker` you can either install it using `brew` or from the
docker website [https://docs.docker.com/docker-for-mac/install/](https://docs.docker.com/docker-for-mac/install/)
:::
## Try out GraphQL
```graphql ```graphql
query { query {

View File

@ -37,9 +37,9 @@ open http://localhost:3000
open http://localhost:8080 open http://localhost:8080
``` ```
::: warning DEMO REQUIREMENTS ::: warning DEMO REQUIREMENTS
This demo requires `docker` you can either install it using `brew` or from the This demo requires `docker` you can either install it using `brew` or from the
docker website https://docs.docker.com/docker-for-mac/install/ docker website [https://docs.docker.com/docker-for-mac/install/](https://docs.docker.com/docker-for-mac/install/)
::: :::
#### Trying out GraphQL #### Trying out GraphQL
@ -49,7 +49,7 @@ We currently support the `query` action which is used for fetching data. Support
#### GQL Query #### GQL Query
```graphql ```graphql
query { query {
users { users {
id id
email email
@ -67,7 +67,7 @@ query {
``` ```
The above GraphQL query returns the JSON result below. It handles all The above GraphQL query returns the JSON result below. It handles all
kinds of complexity without you having to writing a line of code. kinds of complexity without you having to writing a line of code.
For example there is a while greater than `gt` and a limit clause on a child field. And the `avatar` field is renamed to `picture`. The `password` field is blocked and not returned. Finally the relationship between the `users` table and the `products` table is auto discovered and used. For example there is a while greater than `gt` and a limit clause on a child field. And the `avatar` field is renamed to `picture`. The `password` field is blocked and not returned. Finally the relationship between the `users` table and the `products` table is auto discovered and used.
@ -167,7 +167,7 @@ not | not: { or : { quantity : { eq: 0 }, price : { eq: 0 } } } | NOT (quantity
Name | Example | Explained | Name | Example | Explained |
--- | --- | --- | --- | --- | --- |
eq, equals | id : { eq: 100 } | id = 100 eq, equals | id : { eq: 100 } | id = 100
neq, not_equals | id: { not_equals: 100 } | id != 100 neq, not_equals | id: { not_equals: 100 } | id != 100
gt, greater_than | id: { gt: 100 } | id > 100 gt, greater_than | id: { gt: 100 } | id > 100
lt, lesser_than | id: { gt: 100 } | id < 100 lt, lesser_than | id: { gt: 100 } | id < 100
@ -230,7 +230,7 @@ query {
# no duplicate prices returned # no duplicate prices returned
distinct: [ price ] distinct: [ price ]
# only items with an id >= 30 and < 30 are returned # only items with an id >= 30 and < 30 are returned
where: { id: { and: { greater_or_equals: 20, lt: 28 } } }) { where: { id: { and: { greater_or_equals: 20, lt: 28 } } }) {
id id
@ -253,7 +253,7 @@ query {
# Return only matches where the price is less than 10 # Return only matches where the price is less than 10
where: { price: { lt: 10 } } where: { price: { lt: 10 } }
# Use the search_rank to order from the best match to the worst # Use the search_rank to order from the best match to the worst
order_by: { search_rank: desc }) { order_by: { search_rank: desc }) {
id id
@ -331,9 +331,9 @@ You can only have one type of auth enabled. You can either pick Rails or JWT. Un
### Rails Auth (Devise / Warden) ### Rails Auth (Devise / Warden)
Almost all Rails apps use Devise or Warden for authentication. Once the user is Almost all Rails apps use Devise or Warden for authentication. Once the user is
authenticated a session is created with the users ID. The session can either be authenticated a session is created with the users ID. The session can either be
stored in the users browser as a cookie, memcache or redis. If memcache or redis is used then a cookie is set in the users browser with just the session id. stored in the users browser as a cookie, memcache or redis. If memcache or redis is used then a cookie is set in the users browser with just the session id.
Super Graph can handle all these variations including the old and new session formats. Just enable the right `auth` config based on how your rails app is configured. Super Graph can handle all these variations including the old and new session formats. Just enable the right `auth` config based on how your rails app is configured.
@ -379,7 +379,7 @@ auth:
auth: auth:
type: jwt type: jwt
cookie: _app_session cookie: _app_session
jwt: jwt:
provider: auth0 #none provider: auth0 #none
secret: abc335bfcfdb04e50db5bb0a4d67ab9 secret: abc335bfcfdb04e50db5bb0a4d67ab9
@ -428,7 +428,7 @@ auth_fail_block: never
# person: people # person: people
# sheep: sheep # sheep: sheep
auth: auth:
# Can be 'rails' or 'jwt' # Can be 'rails' or 'jwt'
type: rails type: rails
cookie: _app_session cookie: _app_session
@ -444,7 +444,7 @@ auth:
# Found in 'Rails.application.config.secret_key_base' # Found in 'Rails.application.config.secret_key_base'
secret_key_base: 0a248500a64c01184edb4d7ad3a805488f8097ac761b76aaa6c17c01dcb7af03a2f18ba61b2868134b9c7b79a122bc0dadff4367414a2d173297bfea92be5566 secret_key_base: 0a248500a64c01184edb4d7ad3a805488f8097ac761b76aaa6c17c01dcb7af03a2f18ba61b2868134b9c7b79a122bc0dadff4367414a2d173297bfea92be5566
# Remote cookie store. (memcache or redis) # Remote cookie store. (memcache or redis)
# url: redis://127.0.0.1:6379 # url: redis://127.0.0.1:6379
# password: test # password: test
@ -471,16 +471,16 @@ database:
password: '' password: ''
# pool_size: 10 # pool_size: 10
# max_retries: 0 # max_retries: 0
# log_level: "debug" # log_level: "debug"
# Define variables here that you want to use in filters # Define variables here that you want to use in filters
variables: variables:
account_id: "select account_id from users where id = $user_id" account_id: "select account_id from users where id = $user_id"
# Define defaults to for the field key and values below # Define defaults to for the field key and values below
defaults: defaults:
filter: ["{ user_id: { eq: $user_id } }"] filter: ["{ user_id: { eq: $user_id } }"]
# Fields and table names that you wish to block # Fields and table names that you wish to block
blacklist: blacklist:
- ar_internal_metadata - ar_internal_metadata
@ -500,10 +500,10 @@ database:
filter: [ filter: [
"{ price: { gt: 0 } }", "{ price: { gt: 0 } }",
"{ price: { lt: 8 } }" "{ price: { lt: 8 } }"
] ]
- name: customers - name: customers
# No filter is used for this field not # No filter is used for this field not
# even defaults.filter # even defaults.filter
filter: none filter: none
@ -537,34 +537,7 @@ SG_AUTH_RAILS_REDIS_PASSWORD
SG_AUTH_JWT_PUBLIC_KEY_FILE SG_AUTH_JWT_PUBLIC_KEY_FILE
``` ```
## Deploying Super Graph ## Developing Super Graph
How do I deploy the Super Graph service with my existing rails app? You have several options here. Esentially you need to ensure your app's session cookie will be passed to this service.
### Custom Docker Image
Create a `Dockerfile` like the one below to roll your own
custom Super Graph docker image. And to build it `docker build -t my-super-graph .`
```docker
FROM dosco/super-graph:latest
WORKDIR /app
COPY *.yml ./
```
### Deploy under a subdomain
For this to work you have to ensure that the option `:domain => :all` is added to your rails app config `Application.config.session_store` this will cause your rails app to create session cookies that can be shared with sub-domains. More info here <http://excid3.com/blog/sharing-a-devise-user-session-across-subdomains-with-rails-3/>
### With an NGINX loadbalancer
I'm sure you know how to configure it so that the Super Graph endpoint path `/api/v1/graphql` is routed to wherever you have this service installed within your architecture.
### On Kubernetes
If your Rails app runs on Kubernetes then ensure you have an ingress config deployed that points the path to the service that you have deployed Super Graph under.
### JWT tokens (Auth0, etc)
In that case deploy under a subdomain and configure this service to use JWT authentication. You will need the public key file or secret key. Ensure your web app passes the JWT token with every GQL request in the Authorize header as a `bearer` token.
## Developing Super Graph
If you want to build and run Super Graph from code then the below commands will build the web ui and launch Super Graph in developer mode with a watcher to rebuild on code changes. And the demo rails app is also launched to make it essier to test changes. If you want to build and run Super Graph from code then the below commands will build the web ui and launch Super Graph in developer mode with a watcher to rebuild on code changes. And the demo rails app is also launched to make it essier to test changes.
@ -587,7 +560,6 @@ docker-compose up
``` ```
## MIT License ## MIT License
MIT Licensed | Copyright © 2018-present Vikram Rangnekar MIT Licensed | Copyright © 2018-present Vikram Rangnekar

141
docs/install.md Normal file
View File

@ -0,0 +1,141 @@
---
sidebar: auto
---
## How to deploy Super Graph
Since you're reading this you're probably considering deploying Super Graph. You're in luck it's really easy and there are several ways to choose from. Keep in mind Super Graph can be used as a pre-built docker image or you can easily customize it and build your own docker image.
### Alongside an existing Rails app
Super Graph can read Rails session cookies. Like those created by authentication gems (Devise or Warden). Based on how you've configured your Rails app the cookie can be signed, encrypted, both, include the user ID or just have the ID of the session. If you have choosen to use Redis or Memcache as your session store then Super Graph can read the session cookie and then lookup the user in the session store. In short it works really well with any kind of Rails app setup.
For any of this to work Super Graph must be deployed in a way that make the browser sent your apps cookie to it along with the GraphQL query. This means Super Graph should be on the same domain as your app or a subdomain.
::: tip I need an example
Say your Rails app runs on `myrailsapp.com` then Super Graph should be on the same domain or on a subdomain like `graphql.myrailsapp.com`. If you choose subdomain read below.
:::
### Custom Docker Image
You might find the need to customize the Super Graph config file to fit your app and then package it into a docker image. This is easy to do below is an example `Dockerfile` to do exactly this. And to build it `docker build -t my-super-graph .`
```docker
FROM dosco/super-graph:latest
WORKDIR /app
COPY *.yml ./
```
### Deploy under a subdomain
For this to work you have to ensure that the option `:domain => :all` is added to your Rails app config `Application.config.session_store` this will cause your rails app to create session cookies that can be shared with sub-domains. More info here [/sharing-a-devise-user-session-across-subdomains-with-rails](http://excid3.com/blog/sharing-a-devise-user-session-across-subdomains-with-rails-3/)
### With an NGINX loadbalancer
If you're infrastructure is fronted by NGINX then it should be configured so that all requests to your GraphQL API path are proxyed to Super Graph. In the example NGINX config below all requests to the path `/api/v1/graphql` are routed to wherever you have Super Graph installed within your architecture. This example is derived from the config file example at [/microservices-nginx-gateway/nginx.conf](https://github.com/launchany/microservices-nginx-gateway/blob/master/nginx.conf)
```nginx
# Configuration for the server
server {
# Running port
listen 80;
# Proxy the graphql api path to Super Graph
location /api/v1/graphql {
proxy_pass http://super-graph-service:8080;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
}
# Proxying all other paths to your Rails app
location / {
proxy_pass http://your-rails-app:3000;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
}
}
```
### On Kubernetes
If your Rails app runs on Kubernetes then ensure you have an ingress config deployed that points the path to the service that you have deployed Super Graph under.
#### Ingress config
```yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: simple-rails-app
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: myrailsapp.com
http:
paths:
- path: /api/v1/graphql
backend:
serviceName: graphql-service
servicePort: 8080
- path: /
backend:
serviceName: rails-app
servicePort: 3000
```
#### Service and deployment config
```yaml
apiVersion: v1
kind: Service
metadata:
name: graphql-service
labels:
run: super-graph
spec:
ports:
- port: 8080
protocol: TCP
selector:
run: super-graph
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: super-graph
spec:
selector:
matchLabels:
run: super-graph
replicas: 2
template:
metadata:
labels:
run: super-graph
spec:
containers:
- name: super-graph
image: docker.io/dosco/super-graph:latest
ports:
- containerPort: 8080
```
### JWT tokens (Auth0, etc)
In that case deploy under a subdomain and configure this service to use JWT authentication. You will need the public key file or secret key. Ensure your web app passes the JWT token with every GQL request in the Authorize header as a `bearer` token.