Skip to content

Commit

Permalink
add CloudSQL for CloudRun
Browse files Browse the repository at this point in the history
  • Loading branch information
pydevops committed Aug 8, 2019
1 parent 2cf8ff9 commit 35f038e
Show file tree
Hide file tree
Showing 9 changed files with 216 additions and 0 deletions.
24 changes: 24 additions & 0 deletions cloudrun/sql/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Use the offical Golang image to create a build artifact.
# This is based on Debian and sets the GOPATH to /go.
# https://hub.docker.com/_/golang
FROM golang:1.12 as builder

# Copy local code to the container image.
WORKDIR /go/src/github.com/knative/docs/sql
COPY . .

# Build the command inside the container.
# (You may fetch or manage dependencies here,
# either manually or with a tool like "godep".)
RUN CGO_ENABLED=0 GOOS=linux go build -v -o sql

# Use a Docker multi-stage build to create a lean production image.
# https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds
FROM alpine
RUN apk add --no-cache ca-certificates

# Copy the binary to the production image from the builder stage.
COPY --from=builder /go/src/github.com/knative/docs/sql/sql /sql

# Run the web service on container startup.
CMD ["/sql"]
10 changes: 10 additions & 0 deletions cloudrun/sql/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/bin/bash

# GCP project name
PROJECT_ID=$(gcloud config get-value project)

# modules
go mod tidy
go mod vendor

gcloud builds submit --tag gcr.io/$PROJECT_ID/sql:0.0.1 .
11 changes: 11 additions & 0 deletions cloudrun/sql/cleanup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/bin/bash

# GCP project name
PROJECT=$(gcloud config get-value project)

gcloud beta run services delete visitor \
--platform managed \
--region us-central1

gcloud iam service-accounts delete \
sql-sa@${PROJECT}.iam.gserviceaccount.com
19 changes: 19 additions & 0 deletions cloudrun/sql/create_sa.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/bin/bash

# GCP project name
PROJECT=$(gcloud config get-value project)

gcloud iam service-accounts create sql-sa \
--display-name "Go Run HelloWorld Service Account"

gcloud projects add-iam-policy-binding $PROJECT \
--member serviceAccount:sql-sa@${PROJECT}.iam.gserviceaccount.com \
--role roles/logging.logWriter

gcloud projects add-iam-policy-binding $PROJECT \
--member serviceAccount:sql-sa@${PROJECT}.iam.gserviceaccount.com \
--role roles/cloudtrace.agent
# add cloudsql
gcloud projects add-iam-policy-binding $PROJECT \
--member serviceAccount:sql-sa@${PROJECT}.iam.gserviceaccount.com \
--role roles/cloudsql.client
15 changes: 15 additions & 0 deletions cloudrun/sql/deploy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/usr/bin/env bash
set -eu


# GCP project name
PROJECT=$(gcloud config get-value project)

gcloud beta run deploy visitor \
--allow-unauthenticated \
--image gcr.io/$PROJECT/sql:0.0.1 \
--platform managed \
--region us-central1 \
--set-env-vars "TARGET=CloudSQL,host=mydev-238905:us-central1:demo,db=test,user=app,password=passw0rd" \
--service-account sql-sa@${PROJECT}.iam.gserviceaccount.com \
--add-cloudsql-instances demo
5 changes: 5 additions & 0 deletions cloudrun/sql/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module github.com/pydevops/gcp-labs/cloudrun

go 1.12

require github.com/lib/pq v1.2.0
2 changes: 2 additions & 0 deletions cloudrun/sql/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
126 changes: 126 additions & 0 deletions cloudrun/sql/sql.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package main

import (
"fmt"
"log"
"net/http"
"os"

"database/sql"

_ "github.com/lib/pq"
)

func handler(w http.ResponseWriter, r *http.Request) {
log.Print("Hello world received a request.")
target := os.Getenv("TARGET")
if target == "" {
target = "World"
}
fmt.Fprintf(w, "Hello %s!\n", target)

// Get a list of the most recent visits.
// visits, err := queryVisits(10)
// if err != nil {
// msg := fmt.Sprintf("Could not get recent visits: %v", err)
// http.Error(w, msg, http.StatusInternalServerError)
// return
// }

// // Record this visit.
// if err := recordVisit(time.Now().UnixNano(), r.RemoteAddr); err != nil {
// msg := fmt.Sprintf("Could not save visit: %v", err)
// http.Error(w, msg, http.StatusInternalServerError)
// return
// }

// fmt.Fprintln(w, "Previous visits:")
// for _, v := range visits {
// fmt.Fprintf(w, "[%s] %s\n", time.Unix(0, v.timestamp), v.userIP)
// }
// fmt.Fprintln(w, "\nSuccessfully stored an entry of the current request.")

}

var (
db *sql.DB
connectionName = os.Getenv("host")
dbUser = os.Getenv("user")
dbPass = os.Getenv("password")
dbname = os.Getenv("db")
dsn = fmt.Sprintf("sslmode=disable host=/cloudsql/%s user=%s password=%s dbname=%s", connectionName, dbUser, dbPass, dbname)
)

func main() {
log.Print("sql started.")

var err error
db, err = sql.Open("postgres", dsn)
if err != nil {
log.Fatalf("Could not open db: %v", err)
}
defer db.Close()
err = db.Ping()
if err != nil {
log.Fatal(err)
}

// Only allow 1 connection to the database to avoid overloading it.
db.SetMaxIdleConns(1)
db.SetMaxOpenConns(1)

// Ensure the table exists.
// Running an SQL query also checks the connection to the PostgreSQL server
// is authenticated and valid.
if err := createTable(); err != nil {
log.Fatal(err)
}

http.HandleFunc("/", handler)

port := os.Getenv("PORT")
if port == "" {
port = "8080"
}

log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", port), nil))
}

func createTable() error {
stmt := `CREATE TABLE IF NOT EXISTS visits (
timestamp BIGINT,
userip VARCHAR(255)
)`
_, err := db.Exec(stmt)
return err
}

type visit struct {
timestamp int64
userIP string
}

func recordVisit(timestamp int64, userIP string) error {
stmt := "INSERT INTO visits (timestamp, userip) VALUES ($1, $2)"
_, err := db.Exec(stmt, timestamp, userIP)
return err
}

func queryVisits(limit int64) ([]visit, error) {
rows, err := db.Query("SELECT timestamp, userip FROM visits ORDER BY timestamp DESC LIMIT $1", limit)
if err != nil {
return nil, fmt.Errorf("Could not get recent visits: %v", err)
}
defer rows.Close()

var visits []visit
for rows.Next() {
var v visit
if err := rows.Scan(&v.timestamp, &v.userIP); err != nil {
return nil, fmt.Errorf("Could not get timestamp/user IP out of row: %v", err)
}
visits = append(visits, v)
}

return visits, rows.Err()
}
4 changes: 4 additions & 0 deletions cloudrun/sql/vendor/modules.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# github.com/lib/pq v1.2.0
github.com/lib/pq
github.com/lib/pq/oid
github.com/lib/pq/scram

0 comments on commit 35f038e

Please sign in to comment.