Skip to content
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

Initial implementation of Guestbook example #11

Merged
merged 4 commits into from
Feb 20, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 26 additions & 81 deletions Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Gopkg.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@

[[constraint]]
name = "github.com/terraform-providers/terraform-provider-kubernetes"
version = "1.0.1"
source = "github.com/pulumi/terraform-provider-kubernetes"
branch = "pulumi-master"

[[constraint]]
name = "github.com/ghodss/yaml"
Expand Down
1 change: 1 addition & 0 deletions examples/examples_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ func TestExamples(t *testing.T) {
if !testing.Short() {
examples = append(examples, []integration.ProgramTestOptions{
base.With(integration.ProgramTestOptions{Dir: path.Join(cwd, "nginx")}),
base.With(integration.ProgramTestOptions{Dir: path.Join(cwd, "guestbook")}),
}...)
}

Expand Down
2 changes: 2 additions & 0 deletions examples/guestbook/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/bin/
/node_modules/
4 changes: 4 additions & 0 deletions examples/guestbook/Pulumi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
name: guestbook
runtime: nodejs
description: Kubernetes Guestbook example based on https://kubernetes.io/docs/tutorials/stateless-application/guestbook/

150 changes: 150 additions & 0 deletions examples/guestbook/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
// Copyright 2016-2018, Pulumi Corporation. All rights reserved.

import * as pulumi from "pulumi";
import * as kubernetes from "@pulumi/kubernetes";

// REDIS MASTER
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of a single file, is it worth breaking this apart more similar to https://github.com/kubernetes/kubernetes/tree/master/examples/guestbook? Feels like this will make it a little easier to consume in addition to being more familiar to those who have seen that example code.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, there's a Ksonnet example here https://github.com/ksonnet/ksonnet/blob/master/examples/guestbook.jsonnet which is a single file. May be worth looking at that for inspiration for what "abstractions", if any, might make sense to introduce in the name of shrinking the example even further.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's only separate files in the default guestbook example so that the tutorial can deploy one part at a time and talk about it that way. Like in the ksonnet version, I'd rather find ways to introduce abstractions to simplify the existing code so that it's easier to read in one file. It's rather insane the mount of text needed to do what is logically a very simple set of work here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree. I wrote this before looking at the Ksonnet example and I definitely like the idea of using abstractions to simplify to the point where it obviously belongs in one file 😄


let redisMasterLabels = { app: "redis", tier: "backend", role: "master"};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, variable reuse 😀

let redisMasterService = new kubernetes.Service("redis-master", {
metadata: [{
name: "redis-master",
labels: [redisMasterLabels],
}],
spec: [{
port: [{ port: 6379, targetPort: 6379 }],
selector: [redisMasterLabels],
}],
});
let redisMasterDeployment = new kubernetes.Deployment("redis-master", {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding Ksonnet, it's interesting that they got the creation of services down to a single line, and it's done by the service borrowing fields from the deployment:

redis_master_service: example.service("redis-master") {
    targetPod_: $.redis_master_deployment.spec.template,
},

I assume that's just a simple helper library? Is there any way to get this cheaply "inline" in this file?

metadata: [{
name: "redis-master",
}],
spec: [{
selector: [redisMasterLabels],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't see the selector in the YAML/Ksonnet example. Is this correct?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah sorry guess I totally missed that!

replicas: 1,
template: [{
metadata: [{
labels: [redisMasterLabels],
}],
spec: [{
container: [{
name: "master",
image: "k8s.gcr.io/redis:e2e",
resources: [{
requests: [{
cpu: "100m",
memory: "100Mi",
}]
}],
port: [{
containerPort: 6379,
}],
}],
}],
}],
}],
});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Believe it or not, this is one area where YAML looks nicer, more concise! (Cascading }],s.)

Perhaps gets better with Python.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed - this is fairly ugly relative to YAML.

It does have the benefit of type checking, intellisense, etc. in TypeScript - which is a slight win.

I think we really need to find ways to (a) introduce some named types for common JSON sections and encourage reuse (b) create abstractions for common patterns.


// REDIS SLAVE
let redisSlaveLabels = { app: "redis", tier: "backend", role: "slave" };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it worth making this an array? I.e., [{ app: ... "slave" }]. This would simplify use of the labels below, in both the labels and selector property initializers. (Although, is the fact that these are arrays also an occurrence of pulumi/pulumi-terraform#37?)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once we fix pulumi/pulumi-terraform#37 the arrays will go away - that's why I did it this way.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

let redisSlaveService = new kubernetes.Service("redis-slave", {
metadata: [{
name: "redis-slave",
labels: [redisSlaveLabels],
}],
spec: [{
port: [{ port: 6379, targetPort: 6379 }],
selector: [redisSlaveLabels],
}],
});
let redisSlaveDeployment = new kubernetes.Deployment("redis-slave", {
metadata: [{
name: "redis-slave",
}],
spec: [{
selector: [redisSlaveLabels],
replicas: 1,
template: [{
metadata: [{
labels: [redisSlaveLabels],
}],
spec: [{
container: [{
name: "slave",
image: "gcr.io/google_samples/gb-redisslave:v1",
resources: [{
requests: [{
cpu: "100m",
memory: "100Mi",
}]
}],
env: [{
name: "GET_HOSTS_FROM",
value: "dns",
// If your cluster config does not include a dns service, then to instead access an environment
// variable to find the master service's host, comment out the 'value: dns' line above, and
// uncomment the line below:
// value: "env"
}],
port: [{
containerPort: 6379,
}],
}],
}],
}],
}],
});

// FRONTEND
let frontendLabels = { app: "guestbook", tier: "frontend" };
let frontendService = new kubernetes.Service("frontend", {
metadata: [{
name: "frontend",
labels: [frontendLabels],
}],
spec: [{
// If your cluster supports it, uncomment the following to automatically create
// an external load-balanced IP for the frontend service.
// type: LoadBalancer
port: [{ port: 80 }],
selector: [frontendLabels],
}],
});
let frontendDeployment = new kubernetes.Deployment("frontend", {
metadata: [{
name: "frontend",
}],
spec: [{
selector: [frontendLabels],
replicas: 3,
template: [{
metadata: [{
labels: [frontendLabels],
}],
spec: [{
container: [{
name: "php-redis",
image: "gcr.io/google-samples/gb-frontend:v4",
resources: [{
requests: [{
cpu: "100m",
memory: "100Mi",
}]
}],
env: [{
name: "GET_HOSTS_FROM",
value: "dns",
// If your cluster config does not include a dns service, then to instead access an environment
// variable to find the master service's host, comment out the 'value: dns' line above, and
// uncomment the line below:
// value: "env"
}],
port: [{
containerPort: 80,
}],
}],
}],
}],
}],
});
18 changes: 18 additions & 0 deletions examples/guestbook/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "guestbook",
"version": "0.1",
"main": "bin/index.js",
"typings": "bin/index.d.ts",
"scripts": {
"build": "tsc"
},
"devDependencies": {
"@types/node": "^9.3.0",
"typescript": "^2.5.3"
},
"peerDependencies": {
"@pulumi/kubernetes": "*",
"pulumi": "*"
},
"license": "MIT"
}
21 changes: 21 additions & 0 deletions examples/guestbook/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"compilerOptions": {
"outDir": "bin",
"target": "es6",
"module": "commonjs",
"moduleResolution": "node",
"declaration": true,
"sourceMap": true,
"stripInternal": true,
"experimentalDecorators": true,
"pretty": true,
"noFallthroughCasesInSwitch": true,
"noImplicitAny": true,
"noImplicitReturns": true,
"forceConsistentCasingInFileNames": true,
"strictNullChecks": true
},
"files": [
"index.ts"
]
}
11 changes: 11 additions & 0 deletions examples/guestbook/yarn.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1


"@types/node@^9.3.0":
version "9.4.0"
resolved "https://registry.yarnpkg.com/@types/node/-/node-9.4.0.tgz#b85a0bcf1e1cc84eb4901b7e96966aedc6f078d1"

typescript@^2.5.3:
version "2.7.1"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.7.1.tgz#bb3682c2c791ac90e7c6210b26478a8da085c359"
4 changes: 2 additions & 2 deletions examples/nginx/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as kubernetes from "@pulumi/kubernetes";
// Copyright 2016-2018, Pulumi Corporation. All rights reserved.

kubernetes.config.host = process.env.host;
import * as kubernetes from "@pulumi/kubernetes";

// Create an nginx pod
let nginxcontainer = new kubernetes.Pod("nginx", {
Expand Down
Loading