Skip to content

Commit 7ff8834

Browse files
committed
Add votes-postgres sample
1 parent e675cc2 commit 7ff8834

File tree

13 files changed

+1051
-0
lines changed

13 files changed

+1051
-0
lines changed

azure-votes-postgresql/Dockerfile

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Build the manager binary
2+
FROM golang:1.17.2 as builder
3+
4+
WORKDIR /workspace/
5+
COPY . ./
6+
# cache deps before building and copying source so that we don't need to re-download as much
7+
# and so that source changes don't invalidate our downloaded layer
8+
RUN go mod download
9+
10+
# Build
11+
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GO111MODULE=on go build -a -o azvotes main.go
12+
13+
# Use distroless as minimal base image to package the manager binary
14+
# Refer to https://github.com/GoogleContainerTools/distroless for more details
15+
FROM gcr.io/distroless/static:nonroot
16+
WORKDIR /
17+
COPY --from=builder /workspace/azvotes .
18+
ENTRYPOINT ["/azvotes"]

azure-votes-postgresql/LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
Copyright (c) Microsoft Corporation.
2+
3+
MIT License
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

azure-votes-postgresql/README.md

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
# Azure PostgreSQL Votes Demo App
2+
3+
## About this demo
4+
In this demo, we will walk through creating an Azure Postgres Flexible Server and Postgres database. We will create a simple
5+
application which records votes and stores them in the database.
6+
7+
## Prerequisites
8+
9+
1. An Azure subscription to create Azure resources under.
10+
2. A Kubernetes cluster (at least version 1.21) [created and running](https://kubernetes.io/docs/tutorials/kubernetes-basics/create-cluster/),
11+
and [`kubectl`](https://kubernetes.io/docs/tasks/tools/#kubectl) configured to talk to it. (You can check your cluster
12+
version with `kubectl version`.) This could be a local [Kind cluster](https://kind.sigs.k8s.io/docs/user/quick-start/)
13+
or an [Azure Kubernetes Service cluster](https://docs.microsoft.com/en-us/azure/aks/tutorial-kubernetes-deploy-cluster)
14+
running in your subscription.
15+
3. Azure Service Operator set up and running in your cluster of choice.
16+
Follow the [ASO v2 installation instructions](https://github.com/Azure/azure-service-operator/blob/master/v2/README.md#installation) and
17+
ensure that you can create and delete a simple `ResourceGroup` as shown in the
18+
[usage example](https://github.com/Azure/azure-service-operator/blob/master/v2/README.md#usage).
19+
20+
## Demo
21+
22+
**Step 1: Create environment variables to hold a few key values**
23+
```shell
24+
export SERVER=asodemo-postgres
25+
export USERNAME=asoadmin
26+
export PASSWORD=<yourpassword>
27+
```
28+
29+
**Step 2: Create your Azure Resources**
30+
31+
We use `envsubst` here as a quick and simple way to do basic variable replacement.
32+
33+
```shell
34+
envsubst < manifests/postgres-votes-demo.yaml | kubectl apply -f -
35+
```
36+
37+
This command will create a namespace, along with an Azure `ResourceGroup` along with a PostgreSQL `FlexibleServer`, `FlexibleServerDatabase` and `FlexibleServerFirewallRule`.
38+
It also creates a `Secret` for use later in binding some important connection information into our votes app.
39+
40+
**Note:** In a future iteration of ASO, the username and password fields of the `FlexibleServer` will be specified via a linked `Secret`. See [#1471](https://github.com/Azure/azure-service-operator/issues/1471) for more details.
41+
42+
**Step 3: Check the status of your resources and wait for them to finish provisioning**
43+
```shell
44+
watch kubectl get resourcegroups,flexibleservers,flexibleserversdatabases,flexibleserversfirewallrules -n asodemo
45+
```
46+
47+
It may take a few minutes for the `FlexibleServer` to successfully deploy, during which time you will see:
48+
```shell
49+
NAME READY REASON MESSAGE
50+
asodemo-postgres False Reconciling The resource is in the process of being reconciled by the operator
51+
```
52+
53+
The `FlexibleServersDatabase` cannot be successfully deployed until the `FlexibleServer` it resides in has finished deploying.
54+
While the `FlexibleServer` is being deployed, you will see the database is not deployed and has the following message.
55+
This is ok! Once the `FlexibleServer` has been successfully created in Azure this will resolve itself automatically.
56+
57+
```shell
58+
NAME READY REASON MESSAGE
59+
sampledb False ResourceNotFound The specified resource asodemo-postgres was not found.
60+
```
61+
62+
**Step 4: Create a deployment with a single pod running the Azure PostgreSQL Votes App**
63+
64+
```shell
65+
kubectl apply -f manifests/deploy.yaml
66+
```
67+
68+
Ensure that the pod is running:
69+
```shell
70+
kubectl get pods -n asodemo
71+
```
72+
73+
**Step 5: Port forward to the pod**
74+
75+
```shell
76+
kubectl port-forward -n asodemo deployment/azure-votes-postgresql-deployment 8080:8080
77+
```
78+
79+
**Step 6: Vote!**
80+
81+
Visit `localhost:8080` to vote.
82+
83+
**Step 7: (Optional) look at the data in the database**
84+
85+
You can use the [psql command line](https://www.postgresql.org/docs/current/app-psql.html) to look at the "votes" table.
86+
```shell
87+
psql -h $SERVER.postgres.database.azure.com -p 5432 -U $USERNAME votedb
88+
89+
SELECT * FROM votes;
90+
```
91+
92+
**Step 7: Delete the asodemo namespace**
93+
94+
You don't need to delete the Azure resources individually. The Kubernetes ownership model ensures that when the namespace containing the resources is deleted, the delete is propagated to all resources.
95+
96+
```shell
97+
kubectl delete namespace asodemo
98+
```
99+
100+
## Build the Docker Image
101+
We publish the docker image for you, but if you'd like to build it yourself, run the following commands.
102+
103+
```
104+
docker build -t your_registry.com/your_org_or_user/postgresql_azure_votes:1
105+
docker push your_registry.com/your_org_or_user/postgresql_azure_votes:1
106+
```

azure-votes-postgresql/app.png

34.6 KB
Loading

azure-votes-postgresql/cmd/root.go

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/*
2+
Copyright (c) Microsoft Corporation.
3+
Licensed under the MIT license.
4+
*/
5+
6+
package cmd
7+
8+
import (
9+
"context"
10+
"fmt"
11+
"log"
12+
"os"
13+
14+
"github.com/spf13/cobra"
15+
"github.com/spf13/viper"
16+
17+
"github.com/Azure/azure-votes-postgresql/pkg/azvotes"
18+
)
19+
20+
// rootCmd represents the base command when called without any subcommands
21+
var rootCmd = &cobra.Command{
22+
Use: "azvotes",
23+
Short: "Azure Votes app for postgresql server",
24+
Long: `Starts a web app that demos use of PostgreSQL Server.`,
25+
Run: func(cmd *cobra.Command, args []string) {
26+
27+
user := os.Getenv("USERNAME")
28+
password := os.Getenv("PASSWORD")
29+
server := os.Getenv("SERVER")
30+
database := viper.GetString("DATABASE")
31+
port := viper.GetInt("PORT")
32+
33+
// Confirm that all required fields are set
34+
if user == "" {
35+
log.Fatal("USERNAME environment variable must be set")
36+
}
37+
if password == "" {
38+
log.Fatal("PASSWORD environment variable must be set")
39+
}
40+
if server == "" {
41+
log.Fatal("SERVER environment variable must be set")
42+
}
43+
if database == "" {
44+
log.Fatal("DATABASE environment variable must be set")
45+
}
46+
if port == 0 {
47+
log.Fatal("PORT environment variable must be set")
48+
}
49+
50+
dbClient, err := azvotes.NewClient(server, user, password, port, database)
51+
if err != nil {
52+
log.Fatal(err)
53+
}
54+
55+
ctx := context.Background()
56+
err = dbClient.Ping(ctx)
57+
if err != nil {
58+
log.Fatal(err)
59+
}
60+
log.Println("db is live")
61+
62+
err = dbClient.Init(ctx)
63+
if err != nil {
64+
log.Fatal(err)
65+
}
66+
log.Println("db is initialized")
67+
68+
app := azvotes.NewVoteServer(dbClient)
69+
log.Fatal(app.Start())
70+
},
71+
}
72+
73+
// Execute adds all child commands to the root command and sets flags appropriately.
74+
// This is called by main.main(). It only needs to happen once to the rootCmd.
75+
func Execute() {
76+
if err := rootCmd.Execute(); err != nil {
77+
fmt.Println(err)
78+
os.Exit(1)
79+
}
80+
}
81+
82+
func init() {
83+
84+
viper.AutomaticEnv()
85+
rootCmd.PersistentFlags().StringP("dbuser", "u", "", "database username")
86+
rootCmd.PersistentFlags().StringP("dbpass", "p", "", "database password")
87+
rootCmd.PersistentFlags().StringP("server", "s", "", "server name")
88+
rootCmd.PersistentFlags().StringP("database", "d", "", "database name")
89+
rootCmd.PersistentFlags().IntP("port", "t", 0, "server port")
90+
91+
viper.BindPFlag("dbuser", rootCmd.PersistentFlags().Lookup("dbuser"))
92+
viper.BindPFlag("dbpass", rootCmd.PersistentFlags().Lookup("dbpass"))
93+
viper.BindPFlag("server", rootCmd.PersistentFlags().Lookup("server"))
94+
viper.BindPFlag("database", rootCmd.PersistentFlags().Lookup("database"))
95+
viper.BindPFlag("port", rootCmd.PersistentFlags().Lookup("port"))
96+
viper.SetDefault("port", 1433)
97+
98+
}

azure-votes-postgresql/go.mod

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
module github.com/Azure/azure-votes-postgresql
2+
3+
go 1.17
4+
5+
require (
6+
github.com/jackc/pgx/v4 v4.13.0
7+
github.com/pkg/errors v0.8.1
8+
github.com/spf13/cobra v0.0.5
9+
github.com/spf13/viper v1.4.0
10+
)
11+
12+
require (
13+
github.com/fsnotify/fsnotify v1.4.7 // indirect
14+
github.com/hashicorp/hcl v1.0.0 // indirect
15+
github.com/inconshreveable/mousetrap v1.0.0 // indirect
16+
github.com/jackc/chunkreader/v2 v2.0.1 // indirect
17+
github.com/jackc/pgconn v1.10.0 // indirect
18+
github.com/jackc/pgio v1.0.0 // indirect
19+
github.com/jackc/pgpassfile v1.0.0 // indirect
20+
github.com/jackc/pgproto3/v2 v2.1.1 // indirect
21+
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b // indirect
22+
github.com/jackc/pgtype v1.8.1 // indirect
23+
github.com/magiconair/properties v1.8.0 // indirect
24+
github.com/mitchellh/mapstructure v1.1.2 // indirect
25+
github.com/pelletier/go-toml v1.2.0 // indirect
26+
github.com/spf13/afero v1.1.2 // indirect
27+
github.com/spf13/cast v1.3.0 // indirect
28+
github.com/spf13/jwalterweatherman v1.0.0 // indirect
29+
github.com/spf13/pflag v1.0.3 // indirect
30+
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 // indirect
31+
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 // indirect
32+
golang.org/x/text v0.3.6 // indirect
33+
gopkg.in/yaml.v2 v2.2.2 // indirect
34+
)

0 commit comments

Comments
 (0)