You've already forked golang-saas-starter-kit
mirror of
https://github.com/raseels-repos/golang-saas-starter-kit.git
synced 2025-07-03 00:58:13 +02:00
Merge branch 'master' of gitlab.com:geeks-accelerator/oss/saas-starter-kit into issue8/datadog-lambda-func
This commit is contained in:
@ -87,8 +87,8 @@ webapp:deploy:dev:
|
|||||||
SERVICE: 'web-app'
|
SERVICE: 'web-app'
|
||||||
ENABLE_HTTPS: 1
|
ENABLE_HTTPS: 1
|
||||||
ENABLE_ELB: 0
|
ENABLE_ELB: 0
|
||||||
PRIMARY_HOST: 'eproc.tech'
|
PRIMARY_HOST: 'example.saasstartupkit.com'
|
||||||
HOST_NAMES: 'www.eproc.tech,dev.eproc.tech'
|
HOST_NAMES: 'example.saasstartupkit.com,dev.example.saasstartupkit.com'
|
||||||
S3_BUCKET_PRIVATE: 'saas-starter-kit-private'
|
S3_BUCKET_PRIVATE: 'saas-starter-kit-private'
|
||||||
S3_BUCKET_PUBLIC: 'saas-starter-kit-public'
|
S3_BUCKET_PUBLIC: 'saas-starter-kit-public'
|
||||||
S3_BUCKET_PUBLIC_CLOUDFRONT: 'true'
|
S3_BUCKET_PUBLIC_CLOUDFRONT: 'true'
|
||||||
@ -96,7 +96,7 @@ webapp:deploy:dev:
|
|||||||
STATIC_FILES_IMG_RESIZE: 'true'
|
STATIC_FILES_IMG_RESIZE: 'true'
|
||||||
AWS_USE_ROLE: 'true'
|
AWS_USE_ROLE: 'true'
|
||||||
EMAIL_SENDER: 'lee+saas-starter-kit@geeksinthewoods.com'
|
EMAIL_SENDER: 'lee+saas-starter-kit@geeksinthewoods.com'
|
||||||
WEB_API_BASE_URL: https://api.eproc.tech
|
WEB_API_BASE_URL: https://api.example.saasstartupkit.com
|
||||||
|
|
||||||
webapi:build:dev:
|
webapi:build:dev:
|
||||||
<<: *build_tmpl
|
<<: *build_tmpl
|
||||||
@ -128,8 +128,8 @@ webapi:deploy:dev:
|
|||||||
SERVICE: 'web-api'
|
SERVICE: 'web-api'
|
||||||
ENABLE_HTTPS: 1
|
ENABLE_HTTPS: 1
|
||||||
ENABLE_ELB: 0
|
ENABLE_ELB: 0
|
||||||
PRIMARY_HOST: 'api.eproc.tech'
|
PRIMARY_HOST: 'api.example.saasstartupkit.com'
|
||||||
HOST_NAMES: 'api.dev.eproc.tech'
|
HOST_NAMES: 'api.dev.example.saasstartupkit.com'
|
||||||
S3_BUCKET_PRIVATE: 'saas-starter-kit-private'
|
S3_BUCKET_PRIVATE: 'saas-starter-kit-private'
|
||||||
S3_BUCKET_PUBLIC: 'saas-starter-kit-public'
|
S3_BUCKET_PUBLIC: 'saas-starter-kit-public'
|
||||||
S3_BUCKET_PUBLIC_CLOUDFRONT: 'false'
|
S3_BUCKET_PUBLIC_CLOUDFRONT: 'false'
|
||||||
@ -137,7 +137,7 @@ webapi:deploy:dev:
|
|||||||
STATIC_FILES_IMG_RESIZE: 'false'
|
STATIC_FILES_IMG_RESIZE: 'false'
|
||||||
AWS_USE_ROLE: 'true'
|
AWS_USE_ROLE: 'true'
|
||||||
EMAIL_SENDER: 'lee+saas-starter-kit@geeksinthewoods.com'
|
EMAIL_SENDER: 'lee+saas-starter-kit@geeksinthewoods.com'
|
||||||
WEB_APP_BASE_URL: https://eproc.tech
|
WEB_APP_BASE_URL: https://example.saasstartupkit.com
|
||||||
|
|
||||||
#ddlogscollector:deploy:stage:
|
#ddlogscollector:deploy:stage:
|
||||||
# <<: *deploy_stage_tmpl
|
# <<: *deploy_stage_tmpl
|
||||||
|
142
README.md
142
README.md
@ -62,7 +62,7 @@ delivered to clients.
|
|||||||
a knowledge of a completely different expertise - DevOps. This project provides a complete continuous build pipeline that
|
a knowledge of a completely different expertise - DevOps. This project provides a complete continuous build pipeline that
|
||||||
will push the code to production with minimal effort using serverless deployments to AWS Fargate with GitLab CI/CD.
|
will push the code to production with minimal effort using serverless deployments to AWS Fargate with GitLab CI/CD.
|
||||||
5. Observability - Ensure the code is running as expected in a remote environment. This project implements Datadog to
|
5. Observability - Ensure the code is running as expected in a remote environment. This project implements Datadog to
|
||||||
facilitate exposing metrics, logs and request tracing to obversabe and validate your services are stable and responsive
|
facilitate exposing metrics, logs and request tracing to obverse and validate your services are stable and responsive
|
||||||
for your clients (hopefully paying clients).
|
for your clients (hopefully paying clients).
|
||||||
|
|
||||||
|
|
||||||
@ -71,7 +71,7 @@ facilitate exposing metrics, logs and request tracing to obversabe and validate
|
|||||||
The example project is a complete starter kit for building SasS with GoLang. It provides two example services:
|
The example project is a complete starter kit for building SasS with GoLang. It provides two example services:
|
||||||
* Web App - Responsive web application to provide service to clients. Includes user signup and user authentication for
|
* Web App - Responsive web application to provide service to clients. Includes user signup and user authentication for
|
||||||
direct client interaction via their web browsers.
|
direct client interaction via their web browsers.
|
||||||
* Web API - REST API with JWT authentication that renders results as JSON. This allows clients and other third-pary companies to develop deep
|
* Web API - REST API with JWT authentication that renders results as JSON. This allows clients and other third-party companies to develop deep
|
||||||
integrations with the project.
|
integrations with the project.
|
||||||
|
|
||||||
The example project also provides these tools:
|
The example project also provides these tools:
|
||||||
@ -106,7 +106,7 @@ Accordingly, the project architecture is illustrated with the following diagram.
|
|||||||
With SaaS, a client subscribes to an online service you provide them. The example project provides functionality for
|
With SaaS, a client subscribes to an online service you provide them. The example project provides functionality for
|
||||||
clients to subscribe and then once subscribed they can interact with your software service.
|
clients to subscribe and then once subscribed they can interact with your software service.
|
||||||
|
|
||||||
The initial contributors to this project are building this saas-starter-kit based on their years of experience building enterprise B2B SaaS. Particularily, this saas-starter-kit is based on their most recent experience building the
|
The initial contributors to this project are building this saas-starter-kit based on their years of experience building enterprise B2B SaaS. Particularly, this saas-starter-kit is based on their most recent experience building the
|
||||||
B2B SaaS for [standard operating procedure software](https://keeni.space) (written entirely in Golang). Please refer to the Keeni.Space website,
|
B2B SaaS for [standard operating procedure software](https://keeni.space) (written entirely in Golang). Please refer to the Keeni.Space website,
|
||||||
its [SOP software pricing](https://keeni.space/pricing) and its signup process. The SaaS web app is then available at
|
its [SOP software pricing](https://keeni.space/pricing) and its signup process. The SaaS web app is then available at
|
||||||
[app.keeni.space](https://app.keeni.space). They plan on leveraging this experience and build it into a simplified set
|
[app.keeni.space](https://app.keeni.space). They plan on leveraging this experience and build it into a simplified set
|
||||||
@ -175,7 +175,7 @@ $ git clone git@gitlab.com:geeks-accelerator/oss/saas-starter-kit.git
|
|||||||
$ cd saas-starter-kit/
|
$ cd saas-starter-kit/
|
||||||
```
|
```
|
||||||
|
|
||||||
If you have Go Modules enabled, you should be able compile the project locally. If you have Go Modulels disabled, see
|
If you have Go Modules enabled, you should be able compile the project locally. If you have Go Modules disabled, see
|
||||||
the next section.
|
the next section.
|
||||||
|
|
||||||
|
|
||||||
@ -269,39 +269,133 @@ builds locally, update `docker-compose.yaml` to define a volume.
|
|||||||
|
|
||||||
### Re-starting a specific Go service for development
|
### Re-starting a specific Go service for development
|
||||||
|
|
||||||
When writing code in an iterative fashion, it is nice to be able to restart a specific service so it will run updated
|
When writing code in an iterative fashion, it is nice to have your change automatically rebuilt. This project uses
|
||||||
Go code. This decreases the overhead of stopping all services with `docker-compose down` and then re-starting all the
|
[github.com/gravityblast/fresh](https://github.com/gravityblast/fresh) to recompile your services that will include most
|
||||||
services again with 'docker-compose up'.
|
changes.
|
||||||
|
|
||||||
|
Fresh is a command line tool that builds and (re)starts your web application everytime you save a Go or template file.
|
||||||
|
|
||||||
|
The (Fresh configuration file](https://gitlab.com/geeks-accelerator/oss/saas-starter-kit/blob/master/fresh-auto-reload.conf)
|
||||||
|
is located in the project root. By default the following folders are watched by Fresh:
|
||||||
|
- handlers
|
||||||
|
- static
|
||||||
|
- templates
|
||||||
|
|
||||||
|
Any changes to [internal/*](https://gitlab.com/geeks-accelerator/oss/saas-starter-kit/tree/master/internal) or
|
||||||
|
additional project dependencies added to [go.mod](https://gitlab.com/geeks-accelerator/oss/saas-starter-kit/blob/master/go.mod)
|
||||||
|
will require the service to be rebuilt.
|
||||||
|
|
||||||
To restart a specific service, first use `docker ps` to see the list of services running.
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ docker ps
|
docker-compose up --build -d web-app
|
||||||
CONTAINER ID IMAGE COMMAND NAMES
|
|
||||||
35043164fd0d example-project/web-api:latest "/gosrv" saas-starter-kit_web-api_1
|
|
||||||
d34c8fc27f3b example-project/web-app:latest "/gosrv" saas-starter-kit_web-app_1
|
|
||||||
fd844456243e postgres:11-alpine "docker-entrypoint.s…" saas-starter-kit_postgres_1
|
|
||||||
dda16bfbb8b5 redis:latest "redis-server --appe…" saas-starter-kit_redis_1
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Then use `docker-compose stop` for a specific service. In the command including the name of service in `docker-compose.yaml` file for the service
|
|
||||||
to shut down. In the example command, we will shut down the web-api service so we can start it again.
|
|
||||||
|
|
||||||
|
### Forking your own copy
|
||||||
|
|
||||||
|
1. Checkout the project
|
||||||
|
|
||||||
|
2. Update references.
|
||||||
```bash
|
```bash
|
||||||
$ docker-compose stop web-app
|
flist=`grep -r "geeks-accelerator/oss/saas-starter-kit" * | awk -F ':' '{print $1}' | sort | uniq`
|
||||||
|
for f in $flist; do echo $f; sed -i "" -e "s#geeks-accelerator/oss/saas-starter-kit#geeks-accelerator/oss/aurora-cam#g" $f; done
|
||||||
|
|
||||||
|
|
||||||
|
flist=`grep -r "saas-starter-kit" * | awk -F ':' '{print $1}' | sort | uniq`
|
||||||
|
for f in $flist; do echo $f; sed -i "" -e "s#saas-starter-kit#aurora-cam#g" $f; done
|
||||||
|
|
||||||
|
|
||||||
|
flist=`grep -r "example-project" * | awk -F ':' '{print $1}' | sort | uniq`
|
||||||
|
for f in $flist; do echo $f; sed -i "" -e "s#example-project#aurora-cam#g" $f; done
|
||||||
|
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
If you are not in the directory for the service you want to restart then navigate to it. We will go to the directory for the
|
3. Create a new AWS Policy with the following details:
|
||||||
web-api.
|
```
|
||||||
|
Name: SaasStarterKitDevServices
|
||||||
|
Description: Defines access for saas-starter-kit services.
|
||||||
|
Policy Document: {
|
||||||
|
"Version": "2012-10-17",
|
||||||
|
"Statement": [
|
||||||
|
{
|
||||||
|
"Sid": "DefaultServiceAccess",
|
||||||
|
"Effect": "Allow",
|
||||||
|
"Action": [
|
||||||
|
"s3:HeadBucket",
|
||||||
|
"s3:ListObjects",
|
||||||
|
"s3:PutObject",
|
||||||
|
"s3:PutObjectAcl",
|
||||||
|
"cloudfront:ListDistributions",
|
||||||
|
"ec2:DescribeNetworkInterfaces",
|
||||||
|
"ec2:DeleteNetworkInterface",
|
||||||
|
"ecs:ListTasks",
|
||||||
|
"ecs:DescribeServices",
|
||||||
|
"ecs:DescribeTasks",
|
||||||
|
"ec2:DescribeNetworkInterfaces",
|
||||||
|
"route53:ListHostedZones",
|
||||||
|
"route53:ListResourceRecordSets",
|
||||||
|
"route53:ChangeResourceRecordSets",
|
||||||
|
"ecs:UpdateService",
|
||||||
|
"ses:SendEmail",
|
||||||
|
"ses:ListIdentities",
|
||||||
|
"ses:GetAccountSendingEnabled",
|
||||||
|
"secretsmanager:ListSecretVersionIds",
|
||||||
|
"secretsmanager:GetSecretValue",
|
||||||
|
"secretsmanager:CreateSecret",
|
||||||
|
"secretsmanager:UpdateSecret",
|
||||||
|
"secretsmanager:RestoreSecret",
|
||||||
|
"secretsmanager:DeleteSecret"
|
||||||
|
],
|
||||||
|
"Resource": "*"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Sid": "ServiceInvokeLambda",
|
||||||
|
"Effect": "Allow",
|
||||||
|
"Action": [
|
||||||
|
"iam:GetRole",
|
||||||
|
"lambda:InvokeFunction",
|
||||||
|
"lambda:ListVersionsByFunction",
|
||||||
|
"lambda:GetFunction",
|
||||||
|
"lambda:InvokeAsync",
|
||||||
|
"lambda:GetFunctionConfiguration",
|
||||||
|
"iam:PassRole",
|
||||||
|
"lambda:GetAlias",
|
||||||
|
"lambda:GetPolicy"
|
||||||
|
],
|
||||||
|
"Resource": [
|
||||||
|
"arn:aws:iam:::role/*",
|
||||||
|
"arn:aws:lambda:::function:*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Sid": "datadoglambda",
|
||||||
|
"Effect": "Allow",
|
||||||
|
"Action": [
|
||||||
|
"cloudwatch:Get*",
|
||||||
|
"cloudwatch:List*",
|
||||||
|
"ec2:Describe*",
|
||||||
|
"support:*",
|
||||||
|
"tag:GetResources",
|
||||||
|
"tag:GetTagKeys",
|
||||||
|
"tag:GetTagValues"
|
||||||
|
],
|
||||||
|
"Resource": "*"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Create a new user with programmatic access and directly attach it the policy `SaasStarterKitDevServices`
|
||||||
|
|
||||||
|
4. Create a new docker-compose config file
|
||||||
```bash
|
```bash
|
||||||
$ cd cmd/web-api/
|
cp sample.env_docker_compose .env_docker_compose
|
||||||
```
|
```
|
||||||
|
|
||||||
Then you can start the service again by running main.go
|
5. Update .env_docker_compose with the Access key ID and Secret access key
|
||||||
```bash
|
|
||||||
$ go run main.go
|
6. Update `.gitlab-ci.yml` with relevant details.
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### Optional. Set AWS and Datadog Configs
|
### Optional. Set AWS and Datadog Configs
|
||||||
|
@ -29,8 +29,9 @@ ENV GO111MODULE="on"
|
|||||||
COPY go.mod .
|
COPY go.mod .
|
||||||
COPY go.sum .
|
COPY go.sum .
|
||||||
RUN go mod download
|
RUN go mod download
|
||||||
|
RUN go get github.com/pilu/fresh
|
||||||
|
|
||||||
FROM build_base_golang AS builder
|
FROM build_base_golang AS dev
|
||||||
|
|
||||||
ARG service
|
ARG service
|
||||||
ARG commit_ref=-
|
ARG commit_ref=-
|
||||||
@ -40,15 +41,22 @@ ARG swagInit
|
|||||||
COPY internal ./internal
|
COPY internal ./internal
|
||||||
|
|
||||||
# Copy cmd specific packages.
|
# Copy cmd specific packages.
|
||||||
COPY cmd/${service} ./cmd/web-api
|
COPY cmd/${service} ./cmd/${service}
|
||||||
COPY cmd/${service}/templates /templates
|
COPY cmd/${service}/templates /templates
|
||||||
#COPY cmd/${service}/static /static
|
#COPY cmd/${service}/static /static
|
||||||
|
|
||||||
# Copy the global templates.
|
# Copy the global templates.
|
||||||
ADD resources/templates/shared /templates/shared
|
ADD resources/templates/shared /templates/shared
|
||||||
|
ADD fresh-auto-reload.conf /runner.conf
|
||||||
|
|
||||||
|
ENV TEMPLATE_DIR=/templates
|
||||||
|
|
||||||
WORKDIR ./cmd/${service}
|
WORKDIR ./cmd/${service}
|
||||||
|
|
||||||
|
ENTRYPOINT ["fresh", "-c", "/runner.conf"]
|
||||||
|
|
||||||
|
FROM dev AS builder
|
||||||
|
|
||||||
# Update the API documentation.
|
# Update the API documentation.
|
||||||
# Disabled for the moment as it takes forever to run, rely on manual execution.
|
# Disabled for the moment as it takes forever to run, rely on manual execution.
|
||||||
RUN if [ "$swagInit" != "" ]; then swag init ; fi
|
RUN if [ "$swagInit" != "" ]; then swag init ; fi
|
||||||
|
@ -254,7 +254,7 @@ swag init
|
|||||||
|
|
||||||
### Additional Swagger Annotations
|
### Additional Swagger Annotations
|
||||||
|
|
||||||
Below are some additional example annotions that can be added to `main.go`
|
Below are some additional example annotations that can be added to `main.go`
|
||||||
```go
|
```go
|
||||||
// @title SaaS Example API
|
// @title SaaS Example API
|
||||||
// @description This provides a public API...
|
// @description This provides a public API...
|
||||||
|
@ -66,8 +66,10 @@ func main() {
|
|||||||
|
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
// Logging
|
// Logging
|
||||||
|
log.SetFlags(log.LstdFlags|log.Lmicroseconds|log.Lshortfile)
|
||||||
|
log.SetPrefix(service+" : ")
|
||||||
|
log := log.New(os.Stdout, log.Prefix() , log.Flags())
|
||||||
|
|
||||||
log := log.New(os.Stdout, service+" : ", log.LstdFlags|log.Lmicroseconds|log.Lshortfile)
|
|
||||||
|
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
// Configuration
|
// Configuration
|
||||||
@ -87,11 +89,11 @@ func main() {
|
|||||||
Service struct {
|
Service struct {
|
||||||
Name string `default:"web-api" envconfig:"NAME"`
|
Name string `default:"web-api" envconfig:"NAME"`
|
||||||
Project string `default:"" envconfig:"PROJECT"`
|
Project string `default:"" envconfig:"PROJECT"`
|
||||||
BaseUrl string `default:"" envconfig:"BASE_URL" example:"http://api.eproc.tech"`
|
BaseUrl string `default:"" envconfig:"BASE_URL" example:"http://api.example.saasstartupkit.com"`
|
||||||
HostNames []string `envconfig:"HOST_NAMES" example:"alternative-subdomain.eproc.tech"`
|
HostNames []string `envconfig:"HOST_NAMES" example:"alternative-subdomain.example.saasstartupkit.com"`
|
||||||
EnableHTTPS bool `default:"false" envconfig:"ENABLE_HTTPS"`
|
EnableHTTPS bool `default:"false" envconfig:"ENABLE_HTTPS"`
|
||||||
TemplateDir string `default:"./templates" envconfig:"TEMPLATE_DIR"`
|
TemplateDir string `default:"./templates" envconfig:"TEMPLATE_DIR"`
|
||||||
WebAppBaseUrl string `default:"http://127.0.0.1:3000" envconfig:"WEB_APP_BASE_URL" example:"www.eproc.tech"`
|
WebAppBaseUrl string `default:"http://127.0.0.1:3000" envconfig:"WEB_APP_BASE_URL" example:"www.example.saasstartupkit.com"`
|
||||||
DebugHost string `default:"0.0.0.0:4000" envconfig:"DEBUG_HOST"`
|
DebugHost string `default:"0.0.0.0:4000" envconfig:"DEBUG_HOST"`
|
||||||
ShutdownTimeout time.Duration `default:"5s" envconfig:"SHUTDOWN_TIMEOUT"`
|
ShutdownTimeout time.Duration `default:"5s" envconfig:"SHUTDOWN_TIMEOUT"`
|
||||||
}
|
}
|
||||||
|
@ -1378,7 +1378,7 @@ func TestUserToken(t *testing.T) {
|
|||||||
|
|
||||||
// Test user token with empty credentials.
|
// Test user token with empty credentials.
|
||||||
{
|
{
|
||||||
expectedStatus := http.StatusUnauthorized
|
expectedStatus := http.StatusBadRequest
|
||||||
|
|
||||||
rt := requestTest{
|
rt := requestTest{
|
||||||
fmt.Sprintf("Token %d using empty request", expectedStatus),
|
fmt.Sprintf("Token %d using empty request", expectedStatus),
|
||||||
@ -1406,8 +1406,24 @@ func TestUserToken(t *testing.T) {
|
|||||||
|
|
||||||
expected := weberror.ErrorResponse{
|
expected := weberror.ErrorResponse{
|
||||||
StatusCode: expectedStatus,
|
StatusCode: expectedStatus,
|
||||||
Error: http.StatusText(expectedStatus),
|
Error: "Field validation error",
|
||||||
Details: "must provide email and password in Basic auth",
|
Fields: []weberror.FieldError{
|
||||||
|
{
|
||||||
|
Field: "username",
|
||||||
|
Value: "",
|
||||||
|
Tag: "required",
|
||||||
|
Error: "username is a required field",
|
||||||
|
Display: "username is a required field",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Field: "password",
|
||||||
|
Value: "",
|
||||||
|
Tag: "required",
|
||||||
|
Error: "password is a required field",
|
||||||
|
Display: "password is a required field",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Details: actual.Details,
|
||||||
StackTrace: actual.StackTrace,
|
StackTrace: actual.StackTrace,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,8 +13,9 @@ ENV GO111MODULE="on"
|
|||||||
COPY go.mod .
|
COPY go.mod .
|
||||||
COPY go.sum .
|
COPY go.sum .
|
||||||
RUN go mod download
|
RUN go mod download
|
||||||
|
RUN go get github.com/pilu/fresh
|
||||||
|
|
||||||
FROM build_base_golang AS builder
|
FROM build_base_golang AS dev
|
||||||
|
|
||||||
ARG service
|
ARG service
|
||||||
ARG commit_ref=-
|
ARG commit_ref=-
|
||||||
@ -23,15 +24,22 @@ ARG commit_ref=-
|
|||||||
COPY internal ./internal
|
COPY internal ./internal
|
||||||
|
|
||||||
# Copy cmd specific packages.
|
# Copy cmd specific packages.
|
||||||
COPY cmd/${service} ./cmd/web-app
|
COPY cmd/${service} ./cmd/${service}
|
||||||
COPY cmd/${service}/templates /templates
|
COPY cmd/${service}/templates /templates
|
||||||
COPY cmd/${service}/static /static
|
COPY cmd/${service}/static /static
|
||||||
|
|
||||||
# Copy the global templates.
|
# Copy the global templates.
|
||||||
ADD resources/templates/shared /templates/shared
|
ADD resources/templates/shared /templates/shared
|
||||||
|
ADD fresh-auto-reload.conf /runner.conf
|
||||||
|
|
||||||
|
ENV TEMPLATE_DIR=/templates
|
||||||
|
|
||||||
WORKDIR ./cmd/${service}
|
WORKDIR ./cmd/${service}
|
||||||
|
|
||||||
|
ENTRYPOINT ["fresh", "-c", "/runner.conf"]
|
||||||
|
|
||||||
|
FROM dev AS builder
|
||||||
|
|
||||||
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags "-X main.build=${commit_ref}" -a -installsuffix nocgo -o /gosrv .
|
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags "-X main.build=${commit_ref}" -a -installsuffix nocgo -o /gosrv .
|
||||||
|
|
||||||
FROM alpine:3.9
|
FROM alpine:3.9
|
||||||
|
@ -24,7 +24,7 @@ http://127.0.0.1:3000/
|
|||||||
|
|
||||||
While the web-api service has
|
While the web-api service has
|
||||||
significant functionality, this web-app service is still in development. Currently this web-app services only resizes
|
significant functionality, this web-app service is still in development. Currently this web-app services only resizes
|
||||||
an image and displays resvised versions of it on the index page. See section below on Future Functionality.
|
an image and displays resized versions of it on the index page. See section below on Future Functionality.
|
||||||
|
|
||||||
If you would like to help, please email twins@geeksinthewoods.com.
|
If you would like to help, please email twins@geeksinthewoods.com.
|
||||||
|
|
||||||
|
@ -249,7 +249,7 @@ func (h *Account) Update(ctx context.Context, w http.ResponseWriter, r *http.Req
|
|||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
data["geonameCountries"] = geonames.ValidGeonameCountries
|
data["geonameCountries"] = geonames.ValidGeonameCountries(ctx)
|
||||||
|
|
||||||
data["countries"], err = geonames.FindCountries(ctx, h.MasterDB, "name", "")
|
data["countries"], err = geonames.FindCountries(ctx, h.MasterDB, "name", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -45,6 +45,7 @@ func APP(shutdown chan os.Signal, log *log.Logger, env webcontext.Env, staticDir
|
|||||||
|
|
||||||
// Build a sitemap.
|
// Build a sitemap.
|
||||||
sm := stm.NewSitemap(1)
|
sm := stm.NewSitemap(1)
|
||||||
|
sm.SetVerbose(false)
|
||||||
sm.SetDefaultHost(projectRoutes.WebAppUrl(""))
|
sm.SetDefaultHost(projectRoutes.WebAppUrl(""))
|
||||||
sm.Create()
|
sm.Create()
|
||||||
|
|
||||||
|
@ -105,7 +105,7 @@ func (h *Signup) Step1(ctx context.Context, w http.ResponseWriter, r *http.Reque
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
data["geonameCountries"] = geonames.ValidGeonameCountries
|
data["geonameCountries"] = geonames.ValidGeonameCountries(ctx)
|
||||||
|
|
||||||
data["countries"], err = geonames.FindCountries(ctx, h.MasterDB, "name", "")
|
data["countries"], err = geonames.FindCountries(ctx, h.MasterDB, "name", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -66,8 +66,10 @@ func main() {
|
|||||||
|
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
// Logging
|
// Logging
|
||||||
|
log.SetFlags(log.LstdFlags|log.Lmicroseconds|log.Lshortfile)
|
||||||
|
log.SetPrefix(service+" : ")
|
||||||
|
log := log.New(os.Stdout, log.Prefix() , log.Flags())
|
||||||
|
|
||||||
log := log.New(os.Stdout, service+" : ", log.LstdFlags|log.Lmicroseconds|log.Lshortfile)
|
|
||||||
|
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
// Configuration
|
// Configuration
|
||||||
@ -87,8 +89,8 @@ func main() {
|
|||||||
Service struct {
|
Service struct {
|
||||||
Name string `default:"web-app" envconfig:"NAME"`
|
Name string `default:"web-app" envconfig:"NAME"`
|
||||||
Project string `default:"" envconfig:"PROJECT"`
|
Project string `default:"" envconfig:"PROJECT"`
|
||||||
BaseUrl string `default:"" envconfig:"BASE_URL" example:"http://eproc.tech"`
|
BaseUrl string `default:"" envconfig:"BASE_URL" example:"http://example.saasstartupkit.com"`
|
||||||
HostNames []string `envconfig:"HOST_NAMES" example:"www.eproc.tech"`
|
HostNames []string `envconfig:"HOST_NAMES" example:"www.example.saasstartupkit.com"`
|
||||||
EnableHTTPS bool `default:"false" envconfig:"ENABLE_HTTPS"`
|
EnableHTTPS bool `default:"false" envconfig:"ENABLE_HTTPS"`
|
||||||
TemplateDir string `default:"./templates" envconfig:"TEMPLATE_DIR"`
|
TemplateDir string `default:"./templates" envconfig:"TEMPLATE_DIR"`
|
||||||
SharedTemplateDir string `default:"../../resources/templates/shared" envconfig:"SHARED_TEMPLATE_DIR"`
|
SharedTemplateDir string `default:"../../resources/templates/shared" envconfig:"SHARED_TEMPLATE_DIR"`
|
||||||
@ -99,10 +101,10 @@ func main() {
|
|||||||
CloudFrontEnabled bool `envconfig:"CLOUDFRONT_ENABLED"`
|
CloudFrontEnabled bool `envconfig:"CLOUDFRONT_ENABLED"`
|
||||||
ImgResizeEnabled bool `envconfig:"IMG_RESIZE_ENABLED"`
|
ImgResizeEnabled bool `envconfig:"IMG_RESIZE_ENABLED"`
|
||||||
}
|
}
|
||||||
WebApiBaseUrl string `default:"http://127.0.0.1:3001" envconfig:"WEB_API_BASE_URL" example:"http://api.eproc.tech"`
|
WebApiBaseUrl string `default:"http://127.0.0.1:3001" envconfig:"WEB_API_BASE_URL" example:"http://api.example.saasstartupkit.com"`
|
||||||
SessionKey string `default:"" envconfig:"SESSION_KEY"`
|
SessionKey string `default:"" envconfig:"SESSION_KEY"`
|
||||||
SessionName string `default:"" envconfig:"SESSION_NAME"`
|
SessionName string `default:"" envconfig:"SESSION_NAME"`
|
||||||
EmailSender string `default:"test@eproc.tech" envconfig:"EMAIL_SENDER"`
|
EmailSender string `default:"test@example.saasstartupkit.com" envconfig:"EMAIL_SENDER"`
|
||||||
DebugHost string `default:"0.0.0.0:4000" envconfig:"DEBUG_HOST"`
|
DebugHost string `default:"0.0.0.0:4000" envconfig:"DEBUG_HOST"`
|
||||||
ShutdownTimeout time.Duration `default:"5s" envconfig:"SHUTDOWN_TIMEOUT"`
|
ShutdownTimeout time.Duration `default:"5s" envconfig:"SHUTDOWN_TIMEOUT"`
|
||||||
}
|
}
|
||||||
@ -774,6 +776,9 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
imgUrlFormatter = func(p string) string {
|
imgUrlFormatter = func(p string) string {
|
||||||
|
if strings.HasPrefix(p, "http") {
|
||||||
|
return p
|
||||||
|
}
|
||||||
baseUrl.Path = p
|
baseUrl.Path = p
|
||||||
return baseUrl.String()
|
return baseUrl.String()
|
||||||
}
|
}
|
||||||
@ -818,7 +823,12 @@ func main() {
|
|||||||
tmplFuncs["S3ImgUrl"] = func(ctx context.Context, p string, size int) string {
|
tmplFuncs["S3ImgUrl"] = func(ctx context.Context, p string, size int) string {
|
||||||
imgUrl := imgUrlFormatter(p)
|
imgUrl := imgUrlFormatter(p)
|
||||||
if cfg.Service.StaticFiles.ImgResizeEnabled {
|
if cfg.Service.StaticFiles.ImgResizeEnabled {
|
||||||
imgUrl, _ = img_resize.S3ImgUrl(ctx, redisClient, staticS3UrlFormatter, awsSession, cfg.Aws.S3BucketPublic, imgResizeS3KeyPrefix, imgUrl, size)
|
var rerr error
|
||||||
|
imgUrl, rerr = img_resize.S3ImgUrl(ctx, redisClient, staticS3UrlFormatter, awsSession, cfg.Aws.S3BucketPublic, imgResizeS3KeyPrefix, imgUrl, size)
|
||||||
|
if rerr != nil {
|
||||||
|
imgUrl = "error"
|
||||||
|
log.Printf("main : S3ImgUrl : %s - %s\n", p, rerr)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return imgUrl
|
return imgUrl
|
||||||
}
|
}
|
||||||
@ -843,6 +853,10 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if web.RequestIsImage(r) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
switch statusCode {
|
switch statusCode {
|
||||||
case http.StatusUnauthorized:
|
case http.StatusUnauthorized:
|
||||||
http.Redirect(w, r, "/user/login?redirect="+url.QueryEscape(r.RequestURI), http.StatusFound)
|
http.Redirect(w, r, "/user/login?redirect="+url.QueryEscape(r.RequestURI), http.StatusFound)
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
{{end}}
|
{{end}}
|
||||||
{{define "content"}}
|
{{define "content"}}
|
||||||
|
|
||||||
<nav aria-label="breadcrumb">
|
<nav aria-label="breadcrumb">
|
||||||
<ol class="breadcrumb">
|
<ol class="breadcrumb">
|
||||||
<li class="breadcrumb-item"><a href="/account">Account</a></li>
|
<li class="breadcrumb-item"><a href="/account">Account</a></li>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
# docker-compose up
|
# docker-compose up
|
||||||
# docker-compose stop
|
# docker-compose stop
|
||||||
# docker-compose down
|
# docker-compose down
|
||||||
version: '3'
|
version: '3.7'
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
main:
|
main:
|
||||||
@ -63,9 +63,12 @@ services:
|
|||||||
image: example-project/web-app:latest
|
image: example-project/web-app:latest
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
|
target: dev
|
||||||
dockerfile: cmd/web-app/Dockerfile
|
dockerfile: cmd/web-app/Dockerfile
|
||||||
args:
|
args:
|
||||||
service: 'web-app'
|
service: 'web-app'
|
||||||
|
volumes:
|
||||||
|
- ./:/go/src/gitlab.com/geeks-accelerator/oss/saas-starter-kit
|
||||||
ports:
|
ports:
|
||||||
- 3000:3000 # WEB APP
|
- 3000:3000 # WEB APP
|
||||||
- 4000:4000 # DEBUG API
|
- 4000:4000 # DEBUG API
|
||||||
@ -99,9 +102,12 @@ services:
|
|||||||
image: example-project/web-api:latest
|
image: example-project/web-api:latest
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
|
target: dev
|
||||||
dockerfile: cmd/web-api/Dockerfile
|
dockerfile: cmd/web-api/Dockerfile
|
||||||
args:
|
args:
|
||||||
service: 'web-api'
|
service: 'web-api'
|
||||||
|
volumes:
|
||||||
|
- ./:/go/src/gitlab.com/geeks-accelerator/oss/saas-starter-kit
|
||||||
ports:
|
ports:
|
||||||
- 3001:3001 # WEB API
|
- 3001:3001 # WEB API
|
||||||
- 4001:4001 # DEBUG API
|
- 4001:4001 # DEBUG API
|
||||||
|
14
fresh-auto-reload.conf
Normal file
14
fresh-auto-reload.conf
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
root: .
|
||||||
|
tmp_path: ./tmp
|
||||||
|
build_name: runner-build
|
||||||
|
build_log: runner-build-errors.log
|
||||||
|
valid_ext: .go, .tpl, .tmpl, .html, .gohtml
|
||||||
|
no_rebuild_ext: .tpl, .tmpl, .html
|
||||||
|
ignored: assets, tmp
|
||||||
|
build_delay: 600
|
||||||
|
colors: 1
|
||||||
|
log_color_main: cyan
|
||||||
|
log_color_build: yellow
|
||||||
|
log_color_runner: green
|
||||||
|
log_color_watcher: magenta
|
||||||
|
log_color_app:
|
12
go.mod
12
go.mod
@ -3,12 +3,9 @@ module geeks-accelerator/oss/saas-starter-kit
|
|||||||
require (
|
require (
|
||||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751
|
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751
|
||||||
github.com/aws/aws-sdk-go v1.23.0
|
github.com/aws/aws-sdk-go v1.23.0
|
||||||
github.com/bobesa/go-domain-util v0.0.0-20180815122459-1d708c097a6a
|
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
||||||
github.com/dimfeld/httptreemux v5.0.1+incompatible
|
github.com/dimfeld/httptreemux v5.0.1+incompatible
|
||||||
github.com/dustin/go-humanize v1.0.0
|
github.com/dustin/go-humanize v1.0.0
|
||||||
github.com/fatih/camelcase v1.0.0
|
|
||||||
github.com/fatih/structtag v1.0.0
|
|
||||||
github.com/geeks-accelerator/files v0.0.0-20190704085106-630677cd5c14
|
github.com/geeks-accelerator/files v0.0.0-20190704085106-630677cd5c14
|
||||||
github.com/geeks-accelerator/sqlxmigrate v0.0.0-20190527223850-4a863a2d30db
|
github.com/geeks-accelerator/sqlxmigrate v0.0.0-20190527223850-4a863a2d30db
|
||||||
github.com/geeks-accelerator/swag v1.6.3
|
github.com/geeks-accelerator/swag v1.6.3
|
||||||
@ -28,33 +25,28 @@ require (
|
|||||||
github.com/iancoleman/strcase v0.0.0-20190422225806-e506e3ef7365
|
github.com/iancoleman/strcase v0.0.0-20190422225806-e506e3ef7365
|
||||||
github.com/ikeikeikeike/go-sitemap-generator/v2 v2.0.2
|
github.com/ikeikeikeike/go-sitemap-generator/v2 v2.0.2
|
||||||
github.com/jmoiron/sqlx v1.2.0
|
github.com/jmoiron/sqlx v1.2.0
|
||||||
github.com/json-iterator/go v1.1.7 // indirect
|
|
||||||
github.com/kelseyhightower/envconfig v1.4.0
|
github.com/kelseyhightower/envconfig v1.4.0
|
||||||
github.com/kr/pty v1.1.8 // indirect
|
|
||||||
github.com/lib/pq v1.2.0
|
github.com/lib/pq v1.2.0
|
||||||
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e // indirect
|
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e // indirect
|
||||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
|
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
|
||||||
github.com/onsi/ginkgo v1.8.0 // indirect
|
github.com/onsi/ginkgo v1.8.0 // indirect
|
||||||
github.com/onsi/gomega v1.5.0
|
github.com/onsi/gomega v1.5.0 // indirect
|
||||||
github.com/pborman/uuid v1.2.0
|
github.com/pborman/uuid v1.2.0
|
||||||
github.com/pkg/errors v0.8.1
|
github.com/pkg/errors v0.8.1
|
||||||
github.com/sergi/go-diff v1.0.0
|
|
||||||
github.com/sethgrid/pester v0.0.0-20190127155807-68a33a018ad0
|
github.com/sethgrid/pester v0.0.0-20190127155807-68a33a018ad0
|
||||||
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24
|
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24
|
||||||
github.com/stretchr/testify v1.3.0
|
github.com/stretchr/testify v1.3.0
|
||||||
github.com/sudo-suhas/symcrypto v1.0.0
|
github.com/sudo-suhas/symcrypto v1.0.0
|
||||||
github.com/ugorji/go v1.1.7 // indirect
|
|
||||||
github.com/urfave/cli v1.21.0
|
github.com/urfave/cli v1.21.0
|
||||||
github.com/xwb1989/sqlparser v0.0.0-20180606152119-120387863bf2
|
github.com/xwb1989/sqlparser v0.0.0-20180606152119-120387863bf2
|
||||||
gitlab.com/geeks-accelerator/oss/devops v0.0.0-20190815180027-17c30c1f4c9e
|
gitlab.com/geeks-accelerator/oss/devops v0.0.0-20190815180027-17c30c1f4c9e
|
||||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4
|
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4
|
||||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7
|
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7
|
||||||
golang.org/x/text v0.3.2
|
|
||||||
golang.org/x/tools v0.0.0-20190807223507-b346f7fd45de // indirect
|
golang.org/x/tools v0.0.0-20190807223507-b346f7fd45de // indirect
|
||||||
gopkg.in/DataDog/dd-trace-go.v1 v1.16.1
|
gopkg.in/DataDog/dd-trace-go.v1 v1.16.1
|
||||||
|
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||||
gopkg.in/go-playground/validator.v9 v9.29.1
|
gopkg.in/go-playground/validator.v9 v9.29.1
|
||||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
||||||
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce
|
|
||||||
)
|
)
|
||||||
|
|
||||||
replace gitlab.com/geeks-accelerator/oss/devops => ../devops
|
replace gitlab.com/geeks-accelerator/oss/devops => ../devops
|
||||||
|
36
go.sum
36
go.sum
@ -8,15 +8,13 @@ github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV
|
|||||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
|
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
|
||||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
github.com/aws/aws-sdk-go v1.21.8 h1:Lv6hW2twBhC6mGZAuWtqplEpIIqtVctJg02sE7Qn0Zw=
|
|
||||||
github.com/aws/aws-sdk-go v1.21.8/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
|
||||||
github.com/aws/aws-sdk-go v1.23.0 h1:ilfJN/vJtFo1XDFxB2YMBYGeOvGZl6Qow17oyD4+Z9A=
|
github.com/aws/aws-sdk-go v1.23.0 h1:ilfJN/vJtFo1XDFxB2YMBYGeOvGZl6Qow17oyD4+Z9A=
|
||||||
github.com/aws/aws-sdk-go v1.23.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
github.com/aws/aws-sdk-go v1.23.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||||
github.com/beevik/etree v1.1.0 h1:T0xke/WvNtMoCqgzPhkX2r4rjY3GDZFi+FjpRZY2Jbs=
|
github.com/beevik/etree v1.1.0 h1:T0xke/WvNtMoCqgzPhkX2r4rjY3GDZFi+FjpRZY2Jbs=
|
||||||
github.com/beevik/etree v1.1.0/go.mod h1:r8Aw8JqVegEf0w2fDnATrX9VpkMcyFeM0FhwO62wh+A=
|
github.com/beevik/etree v1.1.0/go.mod h1:r8Aw8JqVegEf0w2fDnATrX9VpkMcyFeM0FhwO62wh+A=
|
||||||
github.com/bobesa/go-domain-util v0.0.0-20180815122459-1d708c097a6a/go.mod h1:/mf0HzRK9xVv+1puqGSMzCo7bhEcQhiisuUXlMkq2p4=
|
github.com/bobesa/go-domain-util v0.0.0-20180815122459-1d708c097a6a/go.mod h1:/mf0HzRK9xVv+1puqGSMzCo7bhEcQhiisuUXlMkq2p4=
|
||||||
|
github.com/clbanning/mxj v1.8.3 h1:2r/KCJi52w2MRz+K+UMa/1d7DdCjnLqYJfnbr7dYNWI=
|
||||||
github.com/clbanning/mxj v1.8.3/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng=
|
github.com/clbanning/mxj v1.8.3/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng=
|
||||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
|
||||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
@ -27,12 +25,8 @@ github.com/dimfeld/httptreemux v5.0.1+incompatible h1:Qj3gVcDNoOthBAqftuD596rm4w
|
|||||||
github.com/dimfeld/httptreemux v5.0.1+incompatible/go.mod h1:rbUlSV+CCpv/SuqUTP/8Bk2O3LyUV436/yaRGkhP6Z0=
|
github.com/dimfeld/httptreemux v5.0.1+incompatible/go.mod h1:rbUlSV+CCpv/SuqUTP/8Bk2O3LyUV436/yaRGkhP6Z0=
|
||||||
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
|
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
|
||||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||||
github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8=
|
|
||||||
github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc=
|
|
||||||
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
|
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
|
||||||
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
||||||
github.com/fatih/structtag v1.0.0 h1:pTHj65+u3RKWYPSGaU290FpI/dXxTaHdVwVwbcPKmEc=
|
|
||||||
github.com/fatih/structtag v1.0.0/go.mod h1:IKitwq45uXL/yqi5mYghiD3w9H6eTOvI9vnk8tXMphA=
|
|
||||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
github.com/geeks-accelerator/files v0.0.0-20190704085106-630677cd5c14 h1:Rrxsq3gr2TWGdnSWHfRbhP/hcxatCyC9kMgLZ3da75A=
|
github.com/geeks-accelerator/files v0.0.0-20190704085106-630677cd5c14 h1:Rrxsq3gr2TWGdnSWHfRbhP/hcxatCyC9kMgLZ3da75A=
|
||||||
@ -80,10 +74,8 @@ github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg
|
|||||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
|
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
|
||||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
|
github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg=
|
||||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
|
||||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
|
||||||
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
|
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
|
||||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
@ -108,14 +100,12 @@ github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhB
|
|||||||
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
|
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
|
||||||
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
|
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
|
||||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||||
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
|
||||||
github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8=
|
github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8=
|
||||||
github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg=
|
github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg=
|
||||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
|
github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
|
||||||
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
|
|
||||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/leodido/go-urn v1.1.0 h1:Sm1gr51B1kKyfD2BlRcLSiEkffoG96g6TPv6eRoEiB8=
|
github.com/leodido/go-urn v1.1.0 h1:Sm1gr51B1kKyfD2BlRcLSiEkffoG96g6TPv6eRoEiB8=
|
||||||
@ -129,15 +119,14 @@ github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN
|
|||||||
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e h1:hB2xlXdHp/pmPZq0y3QnmWAArdw9PqbmotexnWx/FU8=
|
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e h1:hB2xlXdHp/pmPZq0y3QnmWAArdw9PqbmotexnWx/FU8=
|
||||||
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||||
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||||
|
github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE=
|
||||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||||
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||||
github.com/mattn/go-sqlite3 v1.10.0 h1:jbhqpg7tQe4SupckyijYiy0mJJ/pRyHvXf7JdWK860o=
|
github.com/mattn/go-sqlite3 v1.10.0 h1:jbhqpg7tQe4SupckyijYiy0mJJ/pRyHvXf7JdWK860o=
|
||||||
github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||||
github.com/mattn/go-sqlite3 v1.11.0 h1:LDdKkqtYlom37fkvqs8rMPFKAMe8+SgjbwZ6ex1/A/Q=
|
github.com/mattn/go-sqlite3 v1.11.0 h1:LDdKkqtYlom37fkvqs8rMPFKAMe8+SgjbwZ6ex1/A/Q=
|
||||||
github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
|
||||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
|
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
|
||||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
|
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
|
||||||
@ -156,8 +145,6 @@ github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
|||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
|
|
||||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
|
||||||
github.com/sethgrid/pester v0.0.0-20190127155807-68a33a018ad0 h1:X9XMOYjxEfAYSy3xK1DzO5dMkkWhs9E9UCcS1IERx2k=
|
github.com/sethgrid/pester v0.0.0-20190127155807-68a33a018ad0 h1:X9XMOYjxEfAYSy3xK1DzO5dMkkWhs9E9UCcS1IERx2k=
|
||||||
github.com/sethgrid/pester v0.0.0-20190127155807-68a33a018ad0/go.mod h1:Ad7IjTpvzZO8Fl0vh9AzQ+j/jYZfyp2diGwI8m5q+ns=
|
github.com/sethgrid/pester v0.0.0-20190127155807-68a33a018ad0/go.mod h1:Ad7IjTpvzZO8Fl0vh9AzQ+j/jYZfyp2diGwI8m5q+ns=
|
||||||
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24 h1:pntxY8Ary0t43dCZ5dqY4YTJCObLY1kIXl0uzMv+7DE=
|
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24 h1:pntxY8Ary0t43dCZ5dqY4YTJCObLY1kIXl0uzMv+7DE=
|
||||||
@ -173,9 +160,7 @@ github.com/tinylib/msgp v1.1.0 h1:9fQd+ICuRIu/ue4vxJZu6/LzxN0HwMds2nq/0cFvxHU=
|
|||||||
github.com/tinylib/msgp v1.1.0/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
|
github.com/tinylib/msgp v1.1.0/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
|
||||||
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
||||||
github.com/ugorji/go v1.1.5-pre/go.mod h1:FwP/aQVg39TXzItUBMwnWp9T9gPQnXw4Poh4/oBQZ/0=
|
github.com/ugorji/go v1.1.5-pre/go.mod h1:FwP/aQVg39TXzItUBMwnWp9T9gPQnXw4Poh4/oBQZ/0=
|
||||||
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
|
||||||
github.com/ugorji/go/codec v1.1.5-pre/go.mod h1:tULtS6Gy1AE1yCENaw4Vb//HLH5njI2tfCQDUqRd8fI=
|
github.com/ugorji/go/codec v1.1.5-pre/go.mod h1:tULtS6Gy1AE1yCENaw4Vb//HLH5njI2tfCQDUqRd8fI=
|
||||||
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
|
||||||
github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
|
github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
|
||||||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||||
github.com/urfave/cli v1.21.0 h1:wYSSj06510qPIzGSua9ZqsncMmWE3Zr55KBERygyrxE=
|
github.com/urfave/cli v1.21.0 h1:wYSSj06510qPIzGSua9ZqsncMmWE3Zr55KBERygyrxE=
|
||||||
@ -199,8 +184,6 @@ golang.org/x/net v0.0.0-20190611141213-3f473d35a33a/go.mod h1:z5CRVTTTmAJ677TzLL
|
|||||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 h1:Ao/3l156eZf2AW5wK8a7/smtodRU+gha3+BeqJ69lRk=
|
|
||||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
|
||||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7 h1:fHDIZ2oxGnUZRN6WgWFCbYBjH9uqVPRCUVUDhs0wnbA=
|
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7 h1:fHDIZ2oxGnUZRN6WgWFCbYBjH9uqVPRCUVUDhs0wnbA=
|
||||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
@ -213,23 +196,16 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190610200419-93c9922d18ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190610200419-93c9922d18ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190730183949-1393eb018365 h1:SaXEMXhWzMJThc05vu6uh61Q245r4KaWMrsTedk0FDc=
|
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ=
|
||||||
golang.org/x/sys v0.0.0-20190730183949-1393eb018365/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190606050223-4d9ae51c2468/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
|
||||||
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
golang.org/x/tools v0.0.0-20190611222205-d73e1c7e250b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
golang.org/x/tools v0.0.0-20190611222205-d73e1c7e250b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
golang.org/x/tools v0.0.0-20190730205120-7deaedd405c4 h1:GhbPrljMrt6gCNHHAJcWLDV3nDPFkIm0EEuqY9GtuX0=
|
|
||||||
golang.org/x/tools v0.0.0-20190730205120-7deaedd405c4/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
|
|
||||||
golang.org/x/tools v0.0.0-20190805222050-c5a2fd39b72a h1:0AGI+cC4FJwXNdClvHzfHhJf/yPjKwdo/+m0lPKrdJA=
|
|
||||||
golang.org/x/tools v0.0.0-20190805222050-c5a2fd39b72a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
|
|
||||||
golang.org/x/tools v0.0.0-20190807223507-b346f7fd45de h1:VNumCimp/Bwk6fRqgPHkjiUPZ/vzlpi23/kQTuQ4gBA=
|
golang.org/x/tools v0.0.0-20190807223507-b346f7fd45de h1:VNumCimp/Bwk6fRqgPHkjiUPZ/vzlpi23/kQTuQ4gBA=
|
||||||
golang.org/x/tools v0.0.0-20190807223507-b346f7fd45de/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20190807223507-b346f7fd45de/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc=
|
||||||
@ -239,6 +215,8 @@ google.golang.org/appengine v1.6.1 h1:QzqyMA1tlu6CgqCDUtU9V+ZKhLFT2dkJuANu5QaxI3
|
|||||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||||
gopkg.in/DataDog/dd-trace-go.v1 v1.16.1 h1:Dngw1zun6yTYFHNdzEWBlrJzFA2QJMjSA2sZ4nH2UWo=
|
gopkg.in/DataDog/dd-trace-go.v1 v1.16.1 h1:Dngw1zun6yTYFHNdzEWBlrJzFA2QJMjSA2sZ4nH2UWo=
|
||||||
gopkg.in/DataDog/dd-trace-go.v1 v1.16.1/go.mod h1:DVp8HmDh8PuTu2Z0fVVlBsyWaC++fzwVCaGWylTe3tg=
|
gopkg.in/DataDog/dd-trace-go.v1 v1.16.1/go.mod h1:DVp8HmDh8PuTu2Z0fVVlBsyWaC++fzwVCaGWylTe3tg=
|
||||||
|
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk=
|
||||||
|
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
@ -251,8 +229,6 @@ gopkg.in/go-playground/validator.v9 v9.29.1 h1:SvGtYmN60a5CVKTOzMSyfzWDeZRxRuGvR
|
|||||||
gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
|
gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
|
||||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE=
|
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE=
|
||||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw=
|
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw=
|
||||||
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce h1:xcEWjVhvbDy+nHP67nPDDpbYrY+ILlfndk4bRioVHaU=
|
|
||||||
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
|
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||||
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
|
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
|
||||||
|
@ -96,6 +96,10 @@ func RegisterEcsServiceTasksRoute53(log *log.Logger, awsSession *session.Session
|
|||||||
return errors.Wrapf(err, "failed to list tasks for cluster '%s' service '%s'", ecsClusterName, ecsServiceName)
|
return errors.Wrapf(err, "failed to list tasks for cluster '%s' service '%s'", ecsClusterName, ecsServiceName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(servceTaskRes.TaskArns) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
taskRes, err := svc.DescribeTasks(&ecs.DescribeTasksInput{
|
taskRes, err := svc.DescribeTasks(&ecs.DescribeTasksInput{
|
||||||
Cluster: aws.String(ecsClusterName),
|
Cluster: aws.String(ecsClusterName),
|
||||||
Tasks: servceTaskRes.TaskArns,
|
Tasks: servceTaskRes.TaskArns,
|
||||||
@ -148,6 +152,10 @@ func RegisterEcsServiceTasksRoute53(log *log.Logger, awsSession *session.Session
|
|||||||
time.Sleep((time.Duration(a) * time.Second * 10) * time.Duration(a))
|
time.Sleep((time.Duration(a) * time.Second * 10) * time.Duration(a))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(networkInterfaceIds) == 0 {
|
||||||
|
return errors.New("Unable to update public IPs. No network interfaces found.")
|
||||||
|
}
|
||||||
|
|
||||||
log.Println("Get public IPs for network interface IDs.")
|
log.Println("Get public IPs for network interface IDs.")
|
||||||
var publicIps []string
|
var publicIps []string
|
||||||
for a := 0; a <= 3; a++ {
|
for a := 0; a <= 3; a++ {
|
||||||
@ -202,7 +210,11 @@ func RegisterEcsServiceTasksRoute53(log *log.Logger, awsSession *session.Session
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add all the A record names with the same set of public IPs.
|
// Add all the A record names with the same set of public IPs.
|
||||||
|
addedNames := make(map[string]bool)
|
||||||
for _, aName := range aNames {
|
for _, aName := range aNames {
|
||||||
|
if addedNames[aName] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
log.Printf("\t\tAdd A record for '%s'.\n", aName)
|
log.Printf("\t\tAdd A record for '%s'.\n", aName)
|
||||||
|
|
||||||
input.ChangeBatch.Changes = append(input.ChangeBatch.Changes, &route53.Change{
|
input.ChangeBatch.Changes = append(input.ChangeBatch.Changes, &route53.Change{
|
||||||
@ -214,6 +226,7 @@ func RegisterEcsServiceTasksRoute53(log *log.Logger, awsSession *session.Session
|
|||||||
Type: aws.String("A"),
|
Type: aws.String("A"),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
addedNames[aName] = true
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := svc.ChangeResourceRecordSets(input)
|
_, err := svc.ChangeResourceRecordSets(input)
|
||||||
|
@ -2,8 +2,8 @@ package tests
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"geeks-accelerator/oss/saas-starter-kit/internal/platform/web/webcontext"
|
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
@ -13,9 +13,14 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"geeks-accelerator/oss/saas-starter-kit/internal/platform/docker"
|
"geeks-accelerator/oss/saas-starter-kit/internal/platform/docker"
|
||||||
|
"geeks-accelerator/oss/saas-starter-kit/internal/platform/web/webcontext"
|
||||||
"geeks-accelerator/oss/saas-starter-kit/internal/schema"
|
"geeks-accelerator/oss/saas-starter-kit/internal/schema"
|
||||||
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/ec2metadata"
|
||||||
"github.com/aws/aws-sdk-go/aws/session"
|
"github.com/aws/aws-sdk-go/aws/session"
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
|
"github.com/kelseyhightower/envconfig"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Success and failure markers.
|
// Success and failure markers.
|
||||||
@ -43,10 +48,72 @@ func New() *Test {
|
|||||||
|
|
||||||
log := log.New(os.Stdout, "TEST : ", log.LstdFlags|log.Lmicroseconds|log.Lshortfile)
|
log := log.New(os.Stdout, "TEST : ", log.LstdFlags|log.Lmicroseconds|log.Lshortfile)
|
||||||
|
|
||||||
|
// =========================================================================
|
||||||
|
// Configuration
|
||||||
|
var cfg struct {
|
||||||
|
Aws struct {
|
||||||
|
AccessKeyID string `envconfig:"AWS_ACCESS_KEY_ID"` // WEB_API_AWS_AWS_ACCESS_KEY_ID or AWS_ACCESS_KEY_ID
|
||||||
|
SecretAccessKey string `envconfig:"AWS_SECRET_ACCESS_KEY" json:"-"` // don't print
|
||||||
|
Region string `default:"us-west-2" envconfig:"AWS_REGION"`
|
||||||
|
UseRole bool `envconfig:"AWS_USE_ROLE"`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// For additional details refer to https://github.com/kelseyhightower/envconfig
|
||||||
|
if err := envconfig.Process("TESTS", &cfg); err != nil {
|
||||||
|
log.Fatalf("startup : Parsing Config : %+v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AWS access keys are required, if roles are enabled, remove any placeholders.
|
||||||
|
if cfg.Aws.UseRole {
|
||||||
|
cfg.Aws.AccessKeyID = ""
|
||||||
|
cfg.Aws.SecretAccessKey = ""
|
||||||
|
|
||||||
|
// Get an AWS session from an implicit source if no explicit
|
||||||
|
// configuration is provided. This is useful for taking advantage of
|
||||||
|
// EC2/ECS instance roles.
|
||||||
|
if cfg.Aws.Region == "" {
|
||||||
|
sess := session.Must(session.NewSession())
|
||||||
|
md := ec2metadata.New(sess)
|
||||||
|
|
||||||
|
var err error
|
||||||
|
cfg.Aws.Region, err = md.Region()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("startup : Load region of ecs metadata : %+v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print the config for our logs. It's important to any credentials in the config
|
||||||
|
// that could expose a security risk are excluded from being json encoded by
|
||||||
|
// applying the tag `json:"-"` to the struct var.
|
||||||
|
{
|
||||||
|
cfgJSON, err := json.MarshalIndent(cfg, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("startup : Marshalling Config to JSON : %+v", err)
|
||||||
|
}
|
||||||
|
log.Printf("startup : Config : %v\n", string(cfgJSON))
|
||||||
|
}
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// Init AWS Session
|
// Init AWS Session
|
||||||
|
var awsSession *session.Session
|
||||||
|
if cfg.Aws.UseRole {
|
||||||
|
// Get an AWS session from an implicit source if no explicit
|
||||||
|
// configuration is provided. This is useful for taking advantage of
|
||||||
|
// EC2/ECS instance roles.
|
||||||
|
awsSession = session.Must(session.NewSession())
|
||||||
|
if cfg.Aws.Region != "" {
|
||||||
|
awsSession.Config.WithRegion(cfg.Aws.Region)
|
||||||
|
}
|
||||||
|
|
||||||
awsSession := session.Must(session.NewSession())
|
log.Printf("startup : AWS : Using role.\n")
|
||||||
|
} else if cfg.Aws.AccessKeyID != "" {
|
||||||
|
creds := credentials.NewStaticCredentials(cfg.Aws.AccessKeyID, cfg.Aws.SecretAccessKey, "")
|
||||||
|
awsSession = session.New(&aws.Config{Region: aws.String(cfg.Aws.Region), Credentials: creds})
|
||||||
|
|
||||||
|
log.Printf("startup : AWS : Using static credentials\n")
|
||||||
|
}
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// Startup Postgres container
|
// Startup Postgres container
|
||||||
@ -93,8 +160,16 @@ func New() *Test {
|
|||||||
log.Fatalf("startup : Register DB : %v", err)
|
log.Fatalf("startup : Register DB : %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set the context with the required values to
|
||||||
|
// process the request.
|
||||||
|
v := webcontext.Values{
|
||||||
|
Now: time.Now(),
|
||||||
|
Env: webcontext.Env_Dev,
|
||||||
|
}
|
||||||
|
ctx := context.WithValue(context.Background(), webcontext.KeyValues, &v)
|
||||||
|
|
||||||
// Execute the migrations
|
// Execute the migrations
|
||||||
if err = schema.Migrate(masterDB, log, true); err != nil {
|
if err = schema.Migrate(ctx, masterDB, log, true); err != nil {
|
||||||
log.Fatalf("main : Migrate : %v", err)
|
log.Fatalf("main : Migrate : %v", err)
|
||||||
}
|
}
|
||||||
log.Printf("main : Migrate : Completed")
|
log.Printf("main : Migrate : Completed")
|
||||||
|
@ -16,6 +16,7 @@ import (
|
|||||||
|
|
||||||
// Headers
|
// Headers
|
||||||
const (
|
const (
|
||||||
|
HeaderAccept = "Accept"
|
||||||
HeaderUpgrade = "Upgrade"
|
HeaderUpgrade = "Upgrade"
|
||||||
HeaderXForwardedFor = "X-Forwarded-For"
|
HeaderXForwardedFor = "X-Forwarded-For"
|
||||||
HeaderXForwardedProto = "X-Forwarded-Proto"
|
HeaderXForwardedProto = "X-Forwarded-Proto"
|
||||||
@ -127,6 +128,11 @@ func RequestIsWebSocket(r *http.Request) bool {
|
|||||||
return strings.ToLower(upgrade) == "websocket"
|
return strings.ToLower(upgrade) == "websocket"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func RequestIsImage(r *http.Request) bool {
|
||||||
|
accept := r.Header.Get(HeaderAccept)
|
||||||
|
return strings.HasPrefix(accept, "image/")
|
||||||
|
}
|
||||||
|
|
||||||
func RequestScheme(r *http.Request) string {
|
func RequestScheme(r *http.Request) string {
|
||||||
// Can't use `r.Request.URL.Scheme`
|
// Can't use `r.Request.URL.Scheme`
|
||||||
// See: https://groups.google.com/forum/#!topic/golang-nuts/pMUkBlQBDF0
|
// See: https://groups.google.com/forum/#!topic/golang-nuts/pMUkBlQBDF0
|
||||||
|
@ -191,6 +191,10 @@ func RenderError(ctx context.Context, w http.ResponseWriter, r *http.Request, er
|
|||||||
}
|
}
|
||||||
v.StatusCode = webErr.Status
|
v.StatusCode = webErr.Status
|
||||||
|
|
||||||
|
if RequestIsImage(r) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
resp := webErr.Response(ctx, true)
|
resp := webErr.Response(ctx, true)
|
||||||
|
|
||||||
data := map[string]interface{}{
|
data := map[string]interface{}{
|
||||||
|
@ -279,6 +279,11 @@ func NewTemplateRenderer(templateDir string, enableHotReload bool, globalViewDat
|
|||||||
// statusCode: the error method calls this function so allow the HTTP Status Code to be set
|
// statusCode: the error method calls this function so allow the HTTP Status Code to be set
|
||||||
// data: map[string]interface{} to allow including additional request and globally defined values.
|
// data: map[string]interface{} to allow including additional request and globally defined values.
|
||||||
func (r *TemplateRenderer) Render(ctx context.Context, w http.ResponseWriter, req *http.Request, templateLayoutName, templateContentName, contentType string, statusCode int, data map[string]interface{}) error {
|
func (r *TemplateRenderer) Render(ctx context.Context, w http.ResponseWriter, req *http.Request, templateLayoutName, templateContentName, contentType string, statusCode int, data map[string]interface{}) error {
|
||||||
|
// Not really anyway to render an image response using a template.
|
||||||
|
if web.RequestIsImage(req) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// If the template has not been rendered yet or hot reload is enabled,
|
// If the template has not been rendered yet or hot reload is enabled,
|
||||||
// then parse the template files.
|
// then parse the template files.
|
||||||
t, ok := r.templates[templateContentName]
|
t, ok := r.templates[templateContentName]
|
||||||
|
@ -3,3 +3,8 @@
|
|||||||
#AWS_REGION=us-west-2
|
#AWS_REGION=us-west-2
|
||||||
#AWS_USE_ROLE=false
|
#AWS_USE_ROLE=false
|
||||||
#DD_API_KEY=
|
#DD_API_KEY=
|
||||||
|
#WEB_APP_AWS_S3_BUCKET_PRIVATE=
|
||||||
|
#WEB_APP_AWS_S3_BUCKET_PUBLIC=
|
||||||
|
#WEB_API_AWS_S3_BUCKET_PRIVATE=
|
||||||
|
#WEB_API_AWS_S3_BUCKET_PUBLIC=
|
||||||
|
#EMAIL_SENDER=
|
||||||
|
@ -26,7 +26,7 @@ in other configuration files. And since this project is open-source, we wanted t
|
|||||||
|
|
||||||
If you don't have an AWS account, signup for one now and then proceed with the deployment setup.
|
If you don't have an AWS account, signup for one now and then proceed with the deployment setup.
|
||||||
|
|
||||||
We assume that if you are deploying the SaaS Stater Kit, you are starting from scratch with no existing dependencies.
|
We assume that if you are deploying the SaaS Starter Kit, you are starting from scratch with no existing dependencies.
|
||||||
This however, excludes any domain names that you would like to use for resolving your services publicly. To use any
|
This however, excludes any domain names that you would like to use for resolving your services publicly. To use any
|
||||||
pre-purchased domain names, make sure they are added to Route 53 in the AWS account. Or you can let the deploy script
|
pre-purchased domain names, make sure they are added to Route 53 in the AWS account. Or you can let the deploy script
|
||||||
create a new zone is Route 53 and update the DNS for the domain name when your ready to make the transition. It is
|
create a new zone is Route 53 and update the DNS for the domain name when your ready to make the transition. It is
|
||||||
@ -235,3 +235,10 @@ instance will be a dedicated host since we need it always up and running, thus i
|
|||||||
```bash
|
```bash
|
||||||
sudo gitlab-runner restart
|
sudo gitlab-runner restart
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go run main.go deploy -service=web-app -env=dev -enable_https=true -primary_host=example.saasstartupkit.com -host_names=example.saasstartupkit.com,dev.example.saasstartupkit.com -private_bucket=saas-starter-kit-private -public_bucket=saas-starter-kit-public -public_bucket_cloudfront=true -static_files_s3=true -static_files_img_resize=1 -recreate_service=0
|
||||||
|
```
|
@ -1,6 +1,7 @@
|
|||||||
package cicd
|
package cicd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"log"
|
"log"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@ -144,7 +145,7 @@ func NewMigrateRequest(log *log.Logger, flags MigrateFlags) (*migrateRequest, er
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Run is the main entrypoint for migration of database schema for a given target environment.
|
// Run is the main entrypoint for migration of database schema for a given target environment.
|
||||||
func Migrate(log *log.Logger, req *migrateRequest) error {
|
func Migrate(log *log.Logger, ctx context.Context, req *migrateRequest) error {
|
||||||
|
|
||||||
// Load the database details.
|
// Load the database details.
|
||||||
var db DB
|
var db DB
|
||||||
@ -200,7 +201,7 @@ func Migrate(log *log.Logger, req *migrateRequest) error {
|
|||||||
|
|
||||||
// Start Migrations
|
// Start Migrations
|
||||||
log.Printf("\t\tStart migrations.")
|
log.Printf("\t\tStart migrations.")
|
||||||
if err = schema.Migrate(masterDb, log, false); err != nil {
|
if err = schema.Migrate(ctx, masterDb, log, false); err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"expvar"
|
"expvar"
|
||||||
|
"geeks-accelerator/oss/saas-starter-kit/internal/platform/web/webcontext"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"geeks-accelerator/oss/saas-starter-kit/tools/devops/cmd/cicd"
|
"geeks-accelerator/oss/saas-starter-kit/tools/devops/cmd/cicd"
|
||||||
_ "github.com/lib/pq"
|
_ "github.com/lib/pq"
|
||||||
@ -111,7 +114,16 @@ func main() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return cicd.ServiceDeploy(log, req)
|
|
||||||
|
// Set the context with the required values to
|
||||||
|
// process the request.
|
||||||
|
v := webcontext.Values{
|
||||||
|
Now: time.Now(),
|
||||||
|
Env: req.Env,
|
||||||
|
}
|
||||||
|
ctx := context.WithValue(context.Background(), webcontext.KeyValues, &v)
|
||||||
|
|
||||||
|
return cicd.ServiceDeploy(log, ctx, req)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -165,7 +177,16 @@ func main() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return cicd.Migrate(log, req)
|
|
||||||
|
// Set the context with the required values to
|
||||||
|
// process the request.
|
||||||
|
v := webcontext.Values{
|
||||||
|
Now: time.Now(),
|
||||||
|
Env: req.Env,
|
||||||
|
}
|
||||||
|
ctx := context.WithValue(context.Background(), webcontext.KeyValues, &v)
|
||||||
|
|
||||||
|
return cicd.Migrate(log, ctx, req)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user