-
Notifications
You must be signed in to change notification settings - Fork 819
samples/guestbook: add sample application #68
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
7bedc38
137ad82
ad7433b
fb0d797
0146eb7
6c23658
9f6c32c
f329ef6
c1cd866
c6da8e9
827fc83
2bb9f57
644086c
dc9029d
feec1e4
c4fda21
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
# Guestbook Sample | ||
|
||
Guestbook is a sample application that records visitors' messages, displays a | ||
cloud banner, and an administrative message. The main business logic is | ||
written in a cloud-agnostic manner using MySQL, the generic blob API, and the | ||
generic runtimevar API. All platform-specific code is set up by Wire. | ||
|
||
## Prerequisites | ||
|
||
You will need to install the following software to run this sample: | ||
|
||
- [Go](https://golang.org/doc/install) and | ||
[vgo](https://go.googlesource.com/vgo) | ||
- [Docker](https://docs.docker.com/install/) | ||
- [Terraform](https://www.terraform.io/intro/getting-started/install.html) | ||
- [jq](https://stedolan.github.io/jq/download/) | ||
- [gcloud CLI](https://cloud.google.com/sdk/downloads), if you want to use GCP | ||
- [aws CLI](https://docs.aws.amazon.com/cli/latest/userguide/installing.html), | ||
if you want to use AWS | ||
|
||
## Building | ||
|
||
`gowire` is not compatible with `vgo` yet, so you must run `vgo vendor` | ||
first to download all the dependencies in `go.mod`. Running `gowire` | ||
generates the Wire code. | ||
|
||
```shell | ||
# First time, for gowire. | ||
$ vgo vendor | ||
|
||
# Now build: | ||
$ gowire && vgo build | ||
``` | ||
|
||
## Running Locally | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Again a quick summary here would be nice. "You will need to run a MySQL database using Docker and then migrate that database. Then, you can start the app locally" or something similar. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||
You will need to run a local MySQL database server, set up a directory that | ||
simulates a bucket, and create a local message of the day. `localdb.sh` is a | ||
script that runs a temporary database using Docker: | ||
|
||
```shell | ||
./localdb.sh | ||
``` | ||
|
||
In another terminal, you can run: | ||
|
||
```shell | ||
# Create the local bucket directory. | ||
mkdir blobs | ||
|
||
# Set a local Message of the Day | ||
echo 'Hello, World!' > motd.txt | ||
|
||
# Run the server. | ||
./guestbook -env=local -bucket=blobs -motd_var=motd.txt | ||
``` | ||
|
||
Your server should be running on http://localhost:8080/. | ||
|
||
You can stop the MySQL database server with Ctrl-\. MySQL ignores Ctrl-C | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a very nice touch. I would have mashed ctrl-c endlessly otherwise. |
||
(SIGINT). | ||
|
||
## Running on Google Cloud Platform (GCP) | ||
|
||
If you want to run this sample on GCP, you need to create a project, download | ||
the gcloud SDK, and log in. You can then use Terraform, a tool for | ||
initializing cloud resources, to set up your project. Finally, this sample | ||
provides a script for building the Guestbook binary and deploying it to the | ||
Kubernetes cluster created by Terraform. | ||
|
||
```shell | ||
gcloud auth application-default login | ||
cd gcp | ||
terraform init | ||
|
||
# Terraform will prompt you for your GCP project ID, desired region, | ||
# and desired zone. | ||
terraform apply | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Granted, I know how to fix this myself by enabling the API (i.e., After running
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ironically, I believe these messages come up because the services are already enabled. :\ Tracking bug is hashicorp/terraform-provider-google#1579 |
||
|
||
./deploy.sh | ||
``` | ||
|
||
The deploy script will display the URL of your running service. | ||
|
||
To clean up the created resources, run `terraform destroy` inside the `gcp` | ||
directory using the same variables you entered during `terraform apply`. | ||
|
||
## Running on Amazon Web Services (AWS) | ||
|
||
If you want to run this sample on AWS, you need to set up an account, download | ||
the AWS command line interface, and log in. You can then use Terraform, a tool | ||
for initializing cloud resources, to set up your project. This will create an | ||
EC2 instance you can connect to and run your binary, copying over the | ||
configuration | ||
|
||
```shell | ||
aws configure | ||
vgo build | ||
cd aws | ||
terraform init | ||
terraform apply -var region=us-west-1 | ||
|
||
# SSH into the EC2 instance. | ||
ssh "admin@$( terraform output instance_host )" | ||
``` | ||
|
||
When you're connected to the server, run the server binary. Replace the | ||
command-line flag values with values from the output of `terraform apply`. | ||
|
||
``` | ||
AWS_REGION=us-west-1 ./guestbook -env=aws \ | ||
-bucket=... -db_host=... -motd_var=... | ||
``` | ||
|
||
You can then visit the server at `http://INSTANCE_HOST:8080/`, where | ||
`INSTANCE_HOST` is the value of `terraform output instance_host` run on your | ||
local machine. | ||
|
||
To clean up the created resources, run `terraform destroy` inside the `aws` | ||
directory using the same variables you entered during `terraform apply`. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,194 @@ | ||
# Copyright 2018 Google LLC | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# https://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
provider "aws" { | ||
version = "~> 1.22" | ||
region = "${var.region}" | ||
} | ||
|
||
provider "random" { | ||
version = "~> 1.3" | ||
} | ||
|
||
# Firewalls | ||
|
||
resource "aws_security_group" "guestbook" { | ||
name_prefix = "guestbook" | ||
description = "Sandbox for the Guestbook Go Cloud sample app." | ||
|
||
ingress { | ||
from_port = 22 | ||
to_port = 22 | ||
protocol = "tcp" | ||
cidr_blocks = ["0.0.0.0/0"] | ||
description = "Public SSH access" | ||
} | ||
|
||
ingress { | ||
from_port = 8080 | ||
to_port = 8080 | ||
protocol = "tcp" | ||
cidr_blocks = ["0.0.0.0/0"] | ||
description = "Public HTTP access" | ||
} | ||
|
||
ingress { | ||
from_port = 3306 | ||
to_port = 3306 | ||
protocol = "tcp" | ||
self = true | ||
description = "MySQL within group" | ||
} | ||
|
||
egress { | ||
from_port = 0 | ||
to_port = 0 | ||
protocol = "-1" | ||
cidr_blocks = ["0.0.0.0/0"] | ||
description = "All outgoing traffic allowed" | ||
} | ||
} | ||
|
||
# SQL Database (RDS) | ||
|
||
resource "random_string" "db_password" { | ||
special = false | ||
length = 20 | ||
} | ||
|
||
resource "aws_db_instance" "guestbook" { | ||
identifier_prefix = "guestbook" | ||
engine = "mysql" | ||
engine_version = "5.6.39" | ||
instance_class = "db.t2.micro" | ||
allocated_storage = 20 | ||
username = "root" | ||
password = "${random_string.db_password.result}" | ||
name = "guestbook" | ||
publicly_accessible = true | ||
vpc_security_group_ids = ["${aws_security_group.guestbook.id}"] | ||
skip_final_snapshot = true | ||
|
||
provisioner "local-exec" { | ||
# TODO(light): Reuse credentials from Terraform. | ||
command = "cat '${path.module}'/../schema.sql '${path.module}'/../roles.sql | '${path.module}'/provision-db.sh '${aws_db_instance.guestbook.address}' '${aws_security_group.guestbook.id}' guestbook '${random_string.db_password.result}'" | ||
} | ||
} | ||
|
||
# Blob Storage (S3) | ||
|
||
resource "aws_s3_bucket" "guestbook" { | ||
bucket_prefix = "guestbook" | ||
} | ||
|
||
# Paramstore (SSM) | ||
|
||
resource "aws_ssm_parameter" "motd" { | ||
name = "${var.paramstore_var}" | ||
type = "String" | ||
value = "ohai from AWS" | ||
} | ||
|
||
# Compute (EC2) | ||
|
||
resource "aws_iam_role" "guestbook" { | ||
name_prefix = "guestbook" | ||
|
||
assume_role_policy = <<EOF | ||
{ | ||
"Version": "2012-10-17", | ||
"Statement": { | ||
"Effect": "Allow", | ||
"Principal": {"Service": "ec2.amazonaws.com"}, | ||
"Action": "sts:AssumeRole" | ||
} | ||
} | ||
EOF | ||
} | ||
|
||
resource "aws_iam_role_policy" "guestbook" { | ||
name_prefix = "Guestbook-Policy" | ||
role = "${aws_iam_role.guestbook.id}" | ||
|
||
policy = <<EOF | ||
{ | ||
"Version": "2012-10-17", | ||
"Statement": { | ||
"Effect": "Allow", | ||
"Action": [ | ||
"s3:GetObject", | ||
"ssm:DescribeParameters", | ||
"ssm:GetParameter", | ||
"ssm:GetParameters", | ||
"xray:PutTraceSegments", | ||
"xray:PutTelemetryRecords" | ||
], | ||
"Resource": "*" | ||
} | ||
} | ||
EOF | ||
} | ||
|
||
resource "aws_iam_instance_profile" "guestbook" { | ||
name_prefix = "guestbook" | ||
role = "${aws_iam_role.guestbook.name}" | ||
} | ||
|
||
data "aws_ami" "debian" { | ||
most_recent = true | ||
|
||
filter { | ||
name = "product-code" | ||
values = ["55q52qvgjfpdj2fpfy9mb1lo4"] | ||
} | ||
|
||
filter { | ||
name = "product-code.type" | ||
values = ["marketplace"] | ||
} | ||
|
||
filter { | ||
name = "architecture" | ||
values = ["x86_64"] | ||
} | ||
|
||
owners = ["679593333241"] | ||
} | ||
|
||
resource "aws_key_pair" "guestbook" { | ||
key_name_prefix = "guestbook" | ||
public_key = "${var.ssh_public_key}" | ||
} | ||
|
||
resource "aws_instance" "guestbook" { | ||
ami = "${data.aws_ami.debian.id}" | ||
instance_type = "t2.micro" | ||
vpc_security_group_ids = ["${aws_security_group.guestbook.id}"] | ||
iam_instance_profile = "${aws_iam_instance_profile.guestbook.id}" | ||
key_name = "${aws_key_pair.guestbook.key_name}" | ||
|
||
connection { | ||
type = "ssh" | ||
user = "admin" | ||
} | ||
|
||
provisioner "file" { | ||
source = "${path.module}/../guestbook" | ||
destination = "/home/admin/guestbook" | ||
} | ||
|
||
provisioner "remote-exec" { | ||
inline = ["chmod +x /home/admin/guestbook"] | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
# Copyright 2018 Google LLC | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# https://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
output "region" { | ||
value = "${var.region}" | ||
description = "Region the resources were created in." | ||
} | ||
|
||
output "bucket" { | ||
value = "${aws_s3_bucket.guestbook.id}" | ||
description = "Name of the S3 bucket created to store images." | ||
} | ||
|
||
output "database_host" { | ||
value = "${aws_db_instance.guestbook.address}" | ||
description = "Host name of the RDS MySQL database." | ||
} | ||
|
||
output "database_root_password" { | ||
value = "${random_string.db_password.result}" | ||
sensitive = true | ||
description = "Password for the root user of the RDS MySQL databse." | ||
} | ||
|
||
output "paramstore_var" { | ||
value = "${var.paramstore_var}" | ||
description = "Location of the SSM Parameter Store Message of the Day variable." | ||
} | ||
|
||
output "instance_host" { | ||
value = "${aws_instance.guestbook.public_ip}" | ||
description = "Address of the EC2 instance." | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be nice to have a few sentences summarizing what this sample does, e.g., "Guestbook is a sample application which records visitors' names. It also demonstrates a common (standard, conventional?) use of go-wire and go-cloud."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.