kubes 0.2.0 → 0.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/.dockerignore +4 -0
  3. data/CHANGELOG.md +16 -1
  4. data/Dockerfile +14 -0
  5. data/docs/_docs/ci/cloudbuild.md +69 -0
  6. data/docs/_docs/config/build-strategy.md +46 -0
  7. data/docs/_docs/dsl/resources/deployment.md +0 -5
  8. data/docs/_docs/dsl/resources/network_policy.md +73 -7
  9. data/docs/_docs/helpers.md +3 -2
  10. data/docs/_docs/learn/dsl/delete.md +2 -0
  11. data/docs/_docs/learn/dsl/deploy.md +5 -0
  12. data/docs/_docs/learn/dsl/new-project.md +1 -0
  13. data/docs/_docs/learn/dsl/review-project.md +13 -2
  14. data/docs/_docs/learn/dsl/update.md +1 -1
  15. data/docs/_docs/learn/yaml/delete.md +2 -0
  16. data/docs/_docs/learn/yaml/deploy.md +5 -0
  17. data/docs/_docs/learn/yaml/new-project.md +1 -0
  18. data/docs/_docs/learn/yaml/review-project.md +27 -16
  19. data/docs/_docs/learn/yaml/update.md +1 -1
  20. data/docs/_docs/yaml.md +0 -5
  21. data/docs/_includes/learn/review.md +3 -1
  22. data/docs/_includes/sidebar.html +6 -0
  23. data/lib/kubes/cli/build.rb +2 -2
  24. data/lib/kubes/cli/docker.rb +2 -2
  25. data/lib/kubes/cli/init.rb +2 -2
  26. data/lib/kubes/compiler/dsl/core/helpers.rb +15 -0
  27. data/lib/kubes/compiler/dsl/syntax/deployment.rb +5 -8
  28. data/lib/kubes/compiler/dsl/syntax/network_policy.rb +29 -12
  29. data/lib/kubes/compiler/shared/helpers.rb +2 -1
  30. data/lib/kubes/config.rb +2 -0
  31. data/lib/kubes/docker.rb +19 -0
  32. data/lib/kubes/docker/strategy/build/base.rb +24 -0
  33. data/lib/kubes/docker/strategy/build/docker.rb +11 -0
  34. data/lib/kubes/docker/strategy/build/gcloud.rb +10 -0
  35. data/lib/kubes/docker/strategy/hooks.rb +9 -0
  36. data/lib/kubes/docker/{base.rb → strategy/image_name.rb} +19 -32
  37. data/lib/kubes/docker/strategy/push/base.rb +9 -0
  38. data/lib/kubes/docker/{push.rb → strategy/push/docker.rb} +2 -5
  39. data/lib/kubes/docker/strategy/push/gcloud.rb +9 -0
  40. data/lib/kubes/docker/strategy/utils.rb +9 -0
  41. data/lib/kubes/version.rb +1 -1
  42. data/lib/templates/dsl/.kubes/resources/base/all.rb.tt +1 -1
  43. data/lib/templates/dsl/.kubes/resources/shared/namespace.rb.tt +2 -0
  44. data/lib/templates/dsl/.kubes/resources/web/{deployment.rb.tt → deployment.rb} +4 -1
  45. data/lib/templates/dsl/.kubes/resources/web/{service.rb.tt → service.rb} +2 -2
  46. data/lib/templates/yaml/.kubes/resources/base/all.yaml.tt +1 -1
  47. data/lib/templates/yaml/.kubes/resources/shared/namespace.yaml.tt +6 -0
  48. data/lib/templates/yaml/.kubes/resources/web/deployment.yaml.tt +2 -7
  49. data/lib/templates/yaml/.kubes/resources/web/service.yaml.tt +2 -2
  50. data/spec/fixtures/syntax/network_policy.rb +1 -1
  51. metadata +20 -7
  52. data/lib/kubes/docker/build.rb +0 -33
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f1705ea4877f8147699b06f43bd7e4e265c45f8ce289d3f54b724b9ca304325c
4
- data.tar.gz: 6473d29cf54233c203af7daec2b78d3128e7b80d78cf739af4705e9a77f8033a
3
+ metadata.gz: 658324c3828bd9f6ee60ad1fd925eb47ff9706fe08256b791e180b0daf3cfba0
4
+ data.tar.gz: 5a2cc328105e6ac7dd7847f4d92697db98827e81b214b7dc3f6b353bf78e224f
5
5
  SHA512:
6
- metadata.gz: aec944078d5b6987b4b8c0f91ef4cd11cd512d2b7f6c007465b93b190c95af55bf4dcf4843d1295ae0ea08bf4b46e8db72cc5bd2bc70dfa7e2db1fd15cfd540e
7
- data.tar.gz: bd470be829eb4545563e6dca41a01a9122f9e045bcbfb462267bd68f6316329f61a02e46b7fd17b9fb3bed7379589c99fc0f47a569a53aae5a2b639886d1cd00
6
+ metadata.gz: 307badb633d97365c4072a7e089c5a36b2abb81e761aa3a5abb46e4aaa4e3da2878023edb12cf203b817ee6aa4484b4d2d758e6f4a20b1e571fdaec75bf61ddc
7
+ data.tar.gz: e5d6f7434c93a73bc996fc661d026f5c601a4bd7c6680c14f0219af4561f1f7ac362370123efe381fac0538021ccb151adc308658b1f3f70c0dbff58334fed9d
@@ -0,0 +1,4 @@
1
+ .git
2
+ pkg
3
+ docs
4
+ spec
@@ -1,8 +1,23 @@
1
- # Change Log
1
+ # Changelog
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
  This project *loosely tries* to adhere to [Semantic Versioning](http://semver.org/), even before v1.0.
5
5
 
6
+ ## [0.2.5]
7
+ - #17 cloudbuild build strategy
8
+
9
+ ## [0.2.4]
10
+ - #16 google cloudbuild support & docs: add Dockerfile for kubes as a docker entrypoint
11
+
12
+ ## [0.2.3]
13
+ - #15 use kubernetes default deployment strategy instead
14
+
15
+ ## [0.2.2]
16
+ - #14 init template updates, dockerfile_port helper
17
+
18
+ ## [0.2.1]
19
+ - #13 improve network policy dsl
20
+
6
21
  ## [0.2.0]
7
22
  - Initial release.
8
23
 
@@ -0,0 +1,14 @@
1
+ FROM ruby:2.7-alpine
2
+
3
+ RUN apk add --no-cache docker
4
+ RUN apk add --no-cache build-base ruby ruby-dev
5
+
6
+ RUN wget https://storage.googleapis.com/kubernetes-release/release/v1.18.6/bin/linux/amd64/kubectl
7
+ RUN chmod u+x kubectl && mv kubectl /bin/kubectl
8
+
9
+ WORKDIR /app
10
+ ADD . /app
11
+ RUN bundle install
12
+ RUN rake install
13
+
14
+ ENTRYPOINT ["/usr/local/bundle/bin/kubes"]
@@ -0,0 +1,69 @@
1
+ ---
2
+ title: CloudBuild
3
+ ---
4
+
5
+ To build kubes as a Docker image entrypoint for [Google CloudBuild Custom Builder](https://cloud.google.com/cloud-build/docs/configuring-builds/use-community-and-custom-builders).
6
+
7
+ git clone http://github.com/boltops-tools/kubes
8
+ cd kubes
9
+ gcloud builds submit --tag gcr.io/$GOOGLE_PROJECT/kubes
10
+
11
+ Be sure to set GOOGLE_PROJECT to your own project id.
12
+
13
+ ## Example Codebuild YAML
14
+
15
+ cloudbuild.yaml:
16
+
17
+ ```yaml
18
+ steps:
19
+ # Simply calling kubectl version with the CLOUDSDK_* vars will auth to the GKE cluster. Unsure why.
20
+ - name: gcr.io/cloud-builders/kubectl
21
+ args: ['version']
22
+ env:
23
+ - 'CLOUDSDK_COMPUTE_REGION=$_GCP_REGION'
24
+ - 'CLOUDSDK_CONTAINER_CLUSTER=$_GKE_CLUSTER'
25
+ - name: 'gcr.io/$PROJECT_ID/kubes'
26
+ args: ["deploy"]
27
+ env:
28
+ - 'GOOGLE_PROJECT=$PROJECT_ID' # .kubes/config.rb: config.repo
29
+ - 'KUBES_ENV=$_KUBES_ENV'
30
+ - 'KUBES_EXTRA=$_KUBES_EXTRA'
31
+
32
+ substitutions:
33
+ _GCP_REGION: us-central1
34
+ _GKE_CLUSTER: dev-cluster
35
+ _KUBES_ENV: dev
36
+ _KUBES_EXTRA: ''
37
+ options:
38
+ substitution_option: 'ALLOW_LOOSE'
39
+ ```
40
+
41
+ ## Run CloudBuild
42
+
43
+ Run cloudbuild with:
44
+
45
+ gcloud builds submit --config cloudbuild.yaml
46
+
47
+ Example with output:
48
+
49
+ $ gcloud builds submit --config cloudbuild.yaml
50
+ Starting Step #1
51
+ Step #1: => docker build -t gcr.io/tung-275700/demo:kubes-2020-07-25T21-13-59 -f Dockerfile .
52
+ Step #1: Pushed gcr.io/tung-275700/demo:kubes-2020-07-25T21-13-59 docker image.
53
+ Step #1: Docker push took 2s.
54
+ Step #1: Compiled .kubes/resources files to .kubes/output
55
+ Step #1: Deploying kubes resources
56
+ Step #1: => kubectl apply -f .kubes/output/shared/namespace.yaml
57
+ Step #1: namespace/demo unchanged
58
+ Step #1: => kubectl apply -f .kubes/output/web/service.yaml
59
+ Step #1: service/web unchanged
60
+ Step #1: => kubectl apply -f .kubes/output/web/deployment.yaml
61
+ Step #1: deployment.apps/web configured
62
+ $
63
+
64
+ ## Create Extra Environments
65
+
66
+ If you are using the [with_extra helper]({% link _docs/extra-env.md %}), you can create additional environments of the same app like so:
67
+
68
+ gcloud builds submit --config cloudbuild.yaml --substitutions=_KUBES_EXTRA=2
69
+ gcloud builds submit --config cloudbuild.yaml --substitutions=_KUBES_EXTRA=3
@@ -0,0 +1,46 @@
1
+ ---
2
+ title: Build Strategy
3
+ ---
4
+
5
+ Kubes uses the `docker` to build the docker image by default. Kubes can also support an additional build strategy: gcloud.
6
+
7
+ ## Gcloud Build Strategy
8
+
9
+ With the gcloud build strategy, you do not need docker installed locally. Google CloudBuild is used to build and push the image to a GCR registry.
10
+
11
+ You must set up the [gcloud cli](https://cloud.google.com/sdk/gcloud/reference/builds/submit). Please refer to the [gcloud sdk install docs](https://cloud.google.com/sdk/install). Kubes will call out to `gcloud builds submit` to create the Docker image.
12
+
13
+ ## Configure
14
+
15
+ You configure gcloud as the build strategy like so:
16
+
17
+ ```ruby
18
+ Kubes.configure do |config|
19
+ config.repo = "gcr.io/#{ENV['GOOGLE_PROJECT']}/demo"
20
+ config.logger.level = "info"
21
+ config.build_strategy = "gcloud" # <= changed to gcloud
22
+ end
23
+ ```
24
+
25
+ ## Commands
26
+
27
+ The kubes builds command will remain the same.
28
+
29
+ kubes docker build
30
+
31
+ There is no need to run the push command, as the build command with the gcloud strategy will always push.
32
+
33
+ ## Deploy
34
+
35
+ The deploy commands remain the same. Example:
36
+
37
+ kubes deploy web
38
+
39
+ If you want to skip the `docker build` phase of the deploy, you can run:
40
+
41
+ kubes deploy web --no-build
42
+
43
+ Also, kubes apply another way to skip the docker build:
44
+
45
+ kubes apply web
46
+
@@ -34,11 +34,6 @@ spec:
34
34
  selector:
35
35
  matchLabels:
36
36
  app: demo
37
- strategy:
38
- rollingUpdate:
39
- maxSurge: 25
40
- maxUnavailable: 25
41
- type: RollingUpdate
42
37
  template:
43
38
  metadata:
44
39
  labels:
@@ -10,9 +10,13 @@ Here's an example of a NetworkPolicy.
10
10
  .kubes/resources/web/network_policy.rb
11
11
 
12
12
  ```ruby
13
- name "demo-web-allow-tester"
14
- matchLabels(role: "web")
15
- fromMatchLabels(run: "tester")
13
+ name "web"
14
+ labels(app: "backend")
15
+ namespace "backend"
16
+
17
+ matchLabels(app: "backend", role: "web")
18
+ fromNamespace(app: "frontend")
19
+ fromPod(app: "backend")
16
20
  ```
17
21
 
18
22
  Produces:
@@ -23,23 +27,85 @@ Produces:
23
27
  apiVersion: networking.k8s.io/v1
24
28
  kind: NetworkPolicy
25
29
  metadata:
26
- name: demo-web-allow-tester
30
+ name: web
31
+ labels:
32
+ app: backend
33
+ namespace: backend
27
34
  spec:
28
35
  podSelector:
29
36
  matchLabels:
37
+ app: backend
30
38
  role: web
31
39
  ingress:
32
40
  - from:
41
+ - namespaceSelector:
42
+ matchLabels:
43
+ app: frontend
33
44
  - podSelector:
34
45
  matchLabels:
35
- run: tester
46
+ app: backend
47
+ ```
48
+
49
+ Note, the behavior of the from is an *or* since the namespaceSelector and podSelector are separate items.
50
+
51
+ ## Example 2
52
+
53
+ If you need more control over the ingress selectors, you can use the `from` method. Here's an example:
54
+
55
+ .kubes/resources/web/network_policy.rb
56
+
57
+ ```ruby
58
+ name "web"
59
+ labels(app: "backend")
60
+ namespace "backend"
61
+
62
+ matchLabels(app: "backend", role: "web")
63
+ from([
64
+ { namespaceSelector: { matchLabels: { app: "frontend" } } },
65
+ { namespaceSelector: { matchLabels: { app: "backend" } } }
66
+ ])
67
+ ```
68
+
69
+ Produces:
70
+
71
+ .kubes/output/web/network_policy.yaml
72
+
73
+ ```yaml
74
+ apiVersion: networking.k8s.io/v1
75
+ kind: NetworkPolicy
76
+ metadata:
77
+ name: web
78
+ labels:
79
+ app: backend
80
+ namespace: backend
81
+ spec:
82
+ podSelector:
83
+ matchLabels:
84
+ app: backend
85
+ role: web
86
+ ingress:
87
+ - from:
88
+ - namespaceSelector:
89
+ matchLabels:
90
+ app: frontend
91
+ - namespaceSelector:
92
+ matchLabels:
93
+ app: backend
36
94
  ```
37
95
 
96
+ This will allow traffic from pods in either the frontend or backend namespaces to the backend pods.
97
+
38
98
  ## DSL Methods
39
99
 
40
100
  Here's a list of more common methods:
41
101
 
42
- * matchLabels
43
- * fromMatchLabels
102
+ * fromNamespace
103
+ * fromPod
104
+ * fromIpBlock
105
+ * toNamespace
106
+ * toPod
107
+ * toIpBlock
108
+ * from
109
+ * to
44
110
 
45
111
  {% include dsl/methods.md name="network_policy" %}
@@ -7,8 +7,9 @@ Kubes provides some helper methods to help write Kubernetes YAML files. Here's
7
7
  Helper | Description
8
8
  --- | ---
9
9
  built_image | Method refers to the latest Docker image built by Kubes. This spares you from having to update the image manually in the deployment resource.
10
- with_extra | Appends the `KUBES_ENV` value to a string if it's set. It's covered in the [Extra Env Docs]({% link _docs/extra-env.md %}).
11
- extra | The `KUBES_ENV` value.
10
+ dockerfile_port | Exposed port extracted from the Dockerfile of the project.
11
+ extra | The `KUBES_EXTRA` value.
12
+ with_extra | Appends the `KUBES_EXTRA` value to a string if it's set. It's covered in the [Extra Env Docs]({% link _docs/extra-env.md %}).
12
13
 
13
14
  Here's also the source code with the helpers: [helpers.rb](https://github.com/boltops-tools/kubes/blob/master/lib/kubes/compiler/shared/helpers.rb).
14
15
 
@@ -15,6 +15,8 @@ You will be prompted to confirm before deletion. Here's out the output looks lik
15
15
  service "demo-web" deleted
16
16
  => kubectl delete -f .kubes/output/web/deployment.yaml
17
17
  deployment.apps "demo-web" deleted
18
+ => kubectl delete -f .kubes/output/shared/namespace.yaml
19
+ namespace "demo" deleted
18
20
  $
19
21
 
20
22
  Let's double-check that the resources have been deleted:
@@ -14,6 +14,8 @@ You'll see output like this:
14
14
  Pushed 111111111111.dkr.ecr.us-west-2.amazonaws.com/demo:kubes-2020-06-19T04-19-13 docker image.
15
15
  Docker push took 15s.
16
16
  Compiled .kubes/resources files
17
+ => kubectl apply -f .kubes/output/shared/namespace.yaml
18
+ namespace/demo created
17
19
  => kubectl apply -f .kubes/output/web/service.yaml
18
20
  service/demo-web created
19
21
  => kubectl apply -f .kubes/output/web/deployment.yaml
@@ -34,6 +36,9 @@ Example output:
34
36
 
35
37
  $ kubes get
36
38
  => kubectl get --recursive -f .kubes/output
39
+ NAME STATUS AGE
40
+ namespace/demo Active 10s
41
+
37
42
  NAME READY UP-TO-DATE AVAILABLE AGE
38
43
  deployment.apps/demo-web 1/1 1 1 10s
39
44
 
@@ -17,6 +17,7 @@ Let's generate a starter project:
17
17
  create .kubes/config/env/dev.rb
18
18
  create .kubes/config/env/prod.rb
19
19
  create .kubes/resources/base/all.rb
20
+ create .kubes/resources/shared/namespace.rb
20
21
  create .kubes/resources/web/deployment.rb
21
22
  create .kubes/resources/web/deployment/dev.rb
22
23
  create .kubes/resources/web/deployment/prod.rb
@@ -4,7 +4,18 @@ title: Review Project
4
4
 
5
5
  Let's review the resources.
6
6
 
7
- ## Deployment Resource
7
+ ## Namespace
8
+
9
+ We'll create a namespace for the app resources:
10
+
11
+ .kubes/resources/shared/namespace.rb
12
+
13
+ ```ruby
14
+ name "demo"
15
+ labels(app: "demo")
16
+ ```
17
+
18
+ ## Deployment
8
19
 
9
20
  The `web/deployment.rb` file is a little more interesting:
10
21
 
@@ -21,7 +32,7 @@ image built_image # IE: user/demo:kubes-2020-06-13T19-55-16-43afc6e
21
32
 
22
33
  The DSL form is more concise than the YAML form. Also, notice the use of the `built_image` helper. The `built_image` is a kubes helper method that refers to the latest Docker image built. This spares you from updating the image manually.
23
34
 
24
- ## Base Resource
35
+ ## Base Folder
25
36
 
26
37
  Also let's check the files in the base folder.
27
38
 
@@ -6,7 +6,7 @@ Let's update the app. In this case, we don't need to update the Docker image, so
6
6
 
7
7
  kubes apply
8
8
 
9
- Here's what the output looks like:
9
+ Here's what the output looks like. Note, the namespace is not shown for conciseness.
10
10
 
11
11
  $ kubes apply
12
12
  Compiled .kubes/resources files
@@ -15,6 +15,8 @@ You will be prompted to confirm before deletion. Here's out the output looks lik
15
15
  service "demo-web" deleted
16
16
  => kubectl delete -f .kubes/output/web/deployment.yaml
17
17
  deployment.apps "demo-web" deleted
18
+ => kubectl delete -f .kubes/output/shared/namespace.yaml
19
+ namespace "demo" deleted
18
20
  $
19
21
 
20
22
  Let's double-check that the resources have been deleted:
@@ -14,6 +14,8 @@ You'll see output like this:
14
14
  Pushed 111111111111.dkr.ecr.us-west-2.amazonaws.com/demo:kubes-2020-06-19T04-19-13 docker image.
15
15
  Docker push took 15s.
16
16
  Compiled .kubes/resources files
17
+ => kubectl apply -f .kubes/output/shared/namespace.yaml
18
+ namespace/demo created
17
19
  => kubectl apply -f .kubes/output/web/service.yaml
18
20
  service/demo-web created
19
21
  => kubectl apply -f .kubes/output/web/deployment.yaml
@@ -34,6 +36,9 @@ Example output:
34
36
 
35
37
  $ kubes get
36
38
  => kubectl get --recursive -f .kubes/output
39
+ NAME STATUS AGE
40
+ namespace/demo Active 7s
41
+
37
42
  NAME READY UP-TO-DATE AVAILABLE AGE
38
43
  deployment.apps/demo-web 1/1 1 1 7s
39
44
 
@@ -19,6 +19,7 @@ Let's generate a starter project:
19
19
  create .kubes/config/env/prod.rb
20
20
  create .kubes/resources/base/all.yaml
21
21
  create .kubes/resources/base/deployment.yaml
22
+ create .kubes/resources/shared/namespace.yaml
22
23
  create .kubes/resources/web/deployment.yaml
23
24
  create .kubes/resources/web/deployment/dev.yaml
24
25
  create .kubes/resources/web/deployment/prod.yaml
@@ -4,7 +4,22 @@ title: Review Project
4
4
 
5
5
  Let's review the resources.
6
6
 
7
- ## Deployment Resource
7
+ ## Namespace
8
+
9
+ We'll create a namespace for the app resources:
10
+
11
+ .kubes/resources/shared/namespace.yaml
12
+
13
+ ```yaml
14
+ apiVersion: v1
15
+ kind: Namespace
16
+ metadata:
17
+ name: demo
18
+ labels:
19
+ app: demo
20
+ ```
21
+
22
+ ## Deployment
8
23
 
9
24
  The `web/deployment.yaml` file is a little more interesting:
10
25
 
@@ -14,7 +29,7 @@ The `web/deployment.yaml` file is a little more interesting:
14
29
  apiVersion: apps/v1
15
30
  kind: Deployment
16
31
  metadata:
17
- name: demo-web
32
+ name: web
18
33
  labels:
19
34
  role: web
20
35
  spec:
@@ -22,24 +37,19 @@ spec:
22
37
  selector:
23
38
  matchLabels:
24
39
  role: web
25
- strategy:
26
- rollingUpdate:
27
- maxSurge: 25
28
- maxUnavailable: 25
29
- type: RollingUpdate
30
40
  template:
31
41
  metadata:
32
42
  labels:
33
43
  role: web
34
44
  spec:
35
45
  containers:
36
- - name: demo
46
+ - name: web
37
47
  image: <%= built_image %>
38
48
  ```
39
49
 
40
50
  Notice the `<%= built_image %>`. Kubes processes the YAML files with ERB templating and replaces these tags. The `built_image` is a kubes helper method that refers to the latest Docker image built by Kubes. This spares you updating the image manually.
41
51
 
42
- ## Base Resource
52
+ ## Base Folder
43
53
 
44
54
  Also let's check the files in the base folder.
45
55
 
@@ -47,7 +57,7 @@ Also let's check the files in the base folder.
47
57
 
48
58
  ```yaml
49
59
  metadata:
50
- namespace: default
60
+ namespace: demo
51
61
  ```
52
62
 
53
63
  .kubes/resources/base/deployment.yaml
@@ -68,6 +78,8 @@ spec:
68
78
 
69
79
  The base folder files are processed first as a part of [Kubes Layering]({% link _docs/layering.md %}). This allows you to define common fields and keep your code DRY.
70
80
 
81
+ The `all.yaml` means all resources will use the demo namespace. The `deployment.yaml` adds common labels to all deployment resource kinds.
82
+
71
83
  ## Service Resource
72
84
 
73
85
  Next, let's look at `service.yaml`
@@ -78,20 +90,19 @@ Next, let's look at `service.yaml`
78
90
  apiVersion: v1
79
91
  kind: Service
80
92
  metadata:
81
- name: demo-web
93
+ name: web
82
94
  labels:
83
- app: demo
84
- namespace: default
95
+ role: web
85
96
  spec:
86
97
  ports:
87
98
  - port: 80
88
99
  protocol: TCP
89
- targetPort: 8080
100
+ targetPort: <%= dockerfile_port %>
90
101
  selector:
91
- app: demo
102
+ role: web
92
103
  type: ClusterIP
93
104
  ```
94
105
 
95
- There's no use of ERB templating here.
106
+ The `dockerfile_port` helper returns the EXPOSE port in the Dockerfile. This spares you updating this manually, you only have to update the Dockerfile.
96
107
 
97
108
  Next, we'll deploy the app.
@@ -6,7 +6,7 @@ Let's update the app. In this case, we don't need to update the Docker image, so
6
6
 
7
7
  kubes apply
8
8
 
9
- Here's what the output looks like:
9
+ Here's what the output looks like. Note, the namespace is not shown for conciseness.
10
10
 
11
11
  $ kubes apply
12
12
  Compiled .kubes/resources files
@@ -30,11 +30,6 @@ spec:
30
30
  selector:
31
31
  matchLabels:
32
32
  app: demo
33
- strategy:
34
- rollingUpdate:
35
- maxSurge: 25
36
- maxUnavailable: 25
37
- type: RollingUpdate
38
33
  template:
39
34
  metadata:
40
35
  labels:
@@ -15,7 +15,7 @@ This is where the `--repo` from `kubes init` got saved. The other options are c
15
15
 
16
16
  ## Dockerfie
17
17
 
18
- The `Dockerfile` is a simple starter example that just runs nginx.
18
+ The `Dockerfile` is a simple starter example that just runs nginx
19
19
 
20
20
  Dockerfile:
21
21
 
@@ -23,3 +23,5 @@ Dockerfile:
23
23
  FROM nginx
24
24
  EXPOSE 80
25
25
  CMD ["nginx", "-g", "daemon off;"]
26
+
27
+ Note: If your project already has a Dockerfile, kubes will use that instead of generating a starter one.
@@ -56,6 +56,7 @@
56
56
  <li><a href="{% link _docs/config/docker.md %}">Docker</a></li>
57
57
  <li><a href="{% link _docs/config/env.md %}">Env</a></li>
58
58
  <li><a href="{% link _docs/config/kubectl.md %}">Kubectl</a></li>
59
+ <li><a href="{% link _docs/config/build-strategy.md %}">Build Strategy</a></li>
59
60
  </ul>
60
61
  </li>
61
62
  <li><a href="{% link _docs/yaml.md %}">YAML</a></li>
@@ -93,6 +94,11 @@
93
94
  </li>
94
95
  <li><a href="{% link _docs/kustomize.md %}">Kustomize Support</a></li>
95
96
  <li><a href="{% link _docs/auto-context.md %}">Auto Context</a></li>
97
+ <li>CI/CD
98
+ <ul>
99
+ <li><a href="{% link _docs/ci/cloudbuild.md %}">CloudBuild</a></li>
100
+ </ul>
101
+ </li>
96
102
  <li>More
97
103
  <ul class="more">
98
104
  <li><a href="{% link support.md %}">Support</a></li>
@@ -1,8 +1,8 @@
1
1
  class Kubes::CLI
2
2
  class Build < Base
3
3
  def run
4
- Kubes::Docker::Build.new(@options).run
5
- Kubes::Docker::Push.new(@options).run
4
+ Kubes::Docker.new(@options, "build").run
5
+ Kubes::Docker.new(@options, "push").run
6
6
  end
7
7
  end
8
8
  end
@@ -4,7 +4,7 @@ class Kubes::CLI
4
4
  long_desc Help.text("docker:build")
5
5
  option :push, type: :boolean, default: false
6
6
  def build
7
- builder = Kubes::Docker::Build.new(options)
7
+ builder = Kubes::Docker.new(options, "build")
8
8
  builder.run
9
9
  push if options[:push]
10
10
  end
@@ -13,7 +13,7 @@ class Kubes::CLI
13
13
  long_desc Help.text("docker:push")
14
14
  option :push, type: :boolean, default: false
15
15
  def push
16
- pusher = Kubes::Docker::Push.new(options)
16
+ pusher = Kubes::Docker.new(options, "push")
17
17
  pusher.run
18
18
  end
19
19
  end
@@ -49,7 +49,7 @@ class Kubes::CLI
49
49
  ignores = %w[
50
50
  .kubes/output
51
51
  .kubes/state
52
- ]
52
+ ].map {|l| "#{l}\n"} # the readlines will have lines with \n so keep consistent for processing
53
53
  if File.exist?(".gitignore")
54
54
  lines = IO.readlines(".gitignore")
55
55
  if lines.detect { |l| l.include?('.kubes/output') }
@@ -61,7 +61,7 @@ class Kubes::CLI
61
61
  lines = ignores
62
62
  end
63
63
 
64
- text = lines.join("\n") + "\n"
64
+ text = lines.join('')
65
65
  IO.write(".gitignore", text)
66
66
  puts "Updated .gitignore"
67
67
  end
@@ -1,4 +1,19 @@
1
1
  module Kubes::Compiler::Dsl::Core
2
2
  module Helpers
3
+ def dockerfile_port
4
+ path = "#{Kubes.root}/Dockerfile"
5
+ File.exist?(path) ? parse_for_dockerfile_port(path) : 80
6
+ end
7
+
8
+ private
9
+ def parse_for_dockerfile_port(path)
10
+ lines = IO.read(path).split("\n")
11
+ expose_line = lines.find { |l| l =~ /^EXPOSE / }
12
+ if expose_line
13
+ md = expose_line.match(/EXPOSE (\d+)/)
14
+ port = md[1] if md
15
+ end
16
+ port ? port.to_i : 80
17
+ end
3
18
  end
4
19
  end
@@ -82,6 +82,11 @@ module Kubes::Compiler::Dsl::Syntax
82
82
  end
83
83
 
84
84
  def default_strategy
85
+ return unless maxUnavailable || maxSurge
86
+
87
+ maxSurge = maxUnavailable if maxUnavailable && !maxSurge
88
+ maxUnavailable = maxSurge if !maxUnavailable && maxSurge
89
+
85
90
  {
86
91
  rollingUpdate: {
87
92
  maxSurge: maxSurge,
@@ -91,14 +96,6 @@ module Kubes::Compiler::Dsl::Syntax
91
96
  }
92
97
  end
93
98
 
94
- def default_maxSurge
95
- 25
96
- end
97
-
98
- def default_maxUnavailable
99
- 25
100
- end
101
-
102
99
  def default_template
103
100
  {
104
101
  metadata: templateMetadata,
@@ -5,8 +5,16 @@ module Kubes::Compiler::Dsl::Syntax
5
5
  :podSelector, # <Object> -required-
6
6
  :policyTypes # <[]string>
7
7
 
8
- fields "fromMatchLabels:hash",
9
- "matchLabels:hash"
8
+ fields "matchLabels:hash"
9
+
10
+ fields "fromNamespace:hash",
11
+ "fromPod:hash",
12
+ "fromIpBlock:hash",
13
+ "toNamespace:hash",
14
+ "toPod:hash",
15
+ "toIpBlock:hash",
16
+ :from,
17
+ :to
10
18
 
11
19
  def default_apiVersion
12
20
  "networking.k8s.io/v1"
@@ -14,17 +22,26 @@ module Kubes::Compiler::Dsl::Syntax
14
22
 
15
23
  def default_spec
16
24
  {
17
- podSelector: {
18
- matchLabels: matchLabels
19
- },
20
- ingress: [
21
- from: [
22
- podSelector: {
23
- matchLabels: fromMatchLabels
24
- }
25
- ]
26
- ]
25
+ podSelector: { matchLabels: matchLabels },
26
+ ingress: [from: from],
27
+ egress: [to: to],
27
28
  }
28
29
  end
30
+
31
+ def default_from
32
+ [
33
+ { namespaceSelector: { matchLabels: fromNamespace } },
34
+ { podSelector: { matchLabels: fromPod } },
35
+ { ipBlock: fromIpBlock }
36
+ ]
37
+ end
38
+
39
+ def default_to
40
+ [
41
+ { namespaceSelector: { matchLabels: toNamespace } },
42
+ { podSelector: { matchLabels: toPod } },
43
+ { ipBlock: toIpBlock }
44
+ ]
45
+ end
29
46
  end
30
47
  end
@@ -20,7 +20,8 @@ module Kubes::Compiler::Shared
20
20
  end
21
21
 
22
22
  def extra
23
- ENV['KUBES_EXTRA']
23
+ extra = ENV['KUBES_EXTRA']
24
+ extra&.strip&.empty? ? nil : extra # if blank string then also return nil
24
25
  end
25
26
 
26
27
  def base64(v)
@@ -35,6 +35,8 @@ module Kubes
35
35
 
36
36
  config.repo = nil # expected to be set by .kubes/config.rb
37
37
 
38
+ config.build_strategy = "docker" # IE: docker or gcloud
39
+
38
40
  config
39
41
  end
40
42
 
@@ -0,0 +1,19 @@
1
+ module Kubes
2
+ class Docker
3
+ def initialize(options, name)
4
+ @options = options
5
+ @name = name
6
+ end
7
+
8
+ def run
9
+ strategy = strategy_class.new(@options, @name) # @name: docker or push
10
+ strategy.run
11
+ end
12
+
13
+ def strategy_class
14
+ strategy = Kubes.config.build_strategy.to_s.camelize # IE: Docker or Gcloud
15
+ klass_name = "Kubes::Docker::Strategy::#{@name.camelize}::#{strategy}"
16
+ klass_name.constantize
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,24 @@
1
+ module Kubes::Docker::Strategy::Build
2
+ class Base
3
+ extend Memoist
4
+ include Kubes::Docker::Strategy::Utils
5
+
6
+ def initialize(options, name)
7
+ @options, @name = options, name
8
+ end
9
+
10
+ def run
11
+ reserve_image_name
12
+ check_dockerfile!
13
+ perform
14
+ store_image_name
15
+ end
16
+
17
+ def check_dockerfile!
18
+ # Dockerfile is also used in args/default.rb, will have to combine if Dockerfile is made configurable
19
+ return if File.exist?("Dockerfile")
20
+ logger.error "ERROR: The Dockerfile does not exist. Cannot build the docker image without a Dockerfile".color(:red)
21
+ exit 1
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,11 @@
1
+ module Kubes::Docker::Strategy::Build
2
+ class Docker < Base
3
+ def perform
4
+ params = args.flatten.join(' ')
5
+ command = "docker build #{params}"
6
+ run_hooks "build" do
7
+ sh(command)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,10 @@
1
+ module Kubes::Docker::Strategy::Build
2
+ class Gcloud < Base
3
+ def perform
4
+ command = "gcloud builds submit --tag #{@@image_name}"
5
+ run_hooks "build" do
6
+ sh(command)
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,9 @@
1
+ module Kubes::Docker::Strategy
2
+ module Hooks
3
+ def run_hooks(name, &block)
4
+ hooks = Kubes::Hooks::Builder.new(name, "#{Kubes.root}/.kubes/config/docker/hooks.rb")
5
+ hooks.build # build hooks
6
+ hooks.run_hooks(&block)
7
+ end
8
+ end
9
+ end
@@ -1,36 +1,6 @@
1
- module Kubes::Docker
2
- class Base
1
+ module Kubes::Docker::Strategy
2
+ module ImageName
3
3
  extend Memoist
4
- include Kubes::Logging
5
- include Kubes::Util::Sh
6
-
7
- def initialize(options={})
8
- @options = options
9
- @name = self.class.name.split('::').last.underscore
10
- end
11
-
12
- def run_hooks(name, &block)
13
- hooks = Kubes::Hooks::Builder.new(name, "#{Kubes.root}/.kubes/config/docker/hooks.rb")
14
- hooks.build # build hooks
15
- hooks.run_hooks(&block)
16
- end
17
-
18
- def args
19
- # base at end in case of redirection. IE: command > /path
20
- custom.args + default.args
21
- end
22
-
23
- def custom
24
- custom = Kubes::Args::Custom.new(@name, "#{Kubes.root}/.kubes/config/docker/args.rb")
25
- custom.build
26
- custom
27
- end
28
- memoize :custom
29
-
30
- def default
31
- Args::Default.new(@name, image_name, @options)
32
- end
33
- memoize :default
34
4
 
35
5
  @@image_name = nil
36
6
  def reserve_image_name
@@ -84,5 +54,22 @@ module Kubes::Docker
84
54
  @git_sha = `cd #{Kubes.root} && git rev-parse --short HEAD`
85
55
  @git_sha.strip!
86
56
  end
57
+
58
+ def args
59
+ # base at end in case of redirection. IE: command > /path
60
+ custom.args + default.args
61
+ end
62
+
63
+ def custom
64
+ custom = Kubes::Args::Custom.new(@name, "#{Kubes.root}/.kubes/config/docker/args.rb")
65
+ custom.build
66
+ custom
67
+ end
68
+ memoize :custom
69
+
70
+ def default
71
+ Kubes::Docker::Args::Default.new(@name, image_name, @options)
72
+ end
73
+ memoize :default
87
74
  end
88
75
  end
@@ -0,0 +1,9 @@
1
+ module Kubes::Docker::Strategy::Push
2
+ class Base
3
+ include Kubes::Docker::Strategy::Utils
4
+
5
+ def initialize(options, name)
6
+ @options, @name = options, name
7
+ end
8
+ end
9
+ end
@@ -1,8 +1,5 @@
1
- module Kubes::Docker
2
- class Push < Base
3
- include Kubes::Logging
4
- include Kubes::Util::Time
5
-
1
+ module Kubes::Docker::Strategy::Push
2
+ class Docker < Base
6
3
  def run
7
4
  update_auth_token
8
5
  start_time = Time.now
@@ -0,0 +1,9 @@
1
+ module Kubes::Docker::Strategy::Push
2
+ class Gcloud < Base
3
+ def run
4
+ run_hooks "push" do
5
+ # noop, gcloud builds submit already pushes the image
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Kubes::Docker::Strategy
2
+ module Utils
3
+ include Kubes::Logging
4
+ include Kubes::Util::Sh
5
+ include Kubes::Util::Time
6
+ include Kubes::Docker::Strategy::ImageName
7
+ include Kubes::Docker::Strategy::Hooks
8
+ end
9
+ end
@@ -1,3 +1,3 @@
1
1
  module Kubes
2
- VERSION = "0.2.0"
2
+ VERSION = "0.2.5"
3
3
  end
@@ -1,2 +1,2 @@
1
- namespace "default"
1
+ namespace "<%= app %>"
2
2
  labels(app: "<%= app %>")
@@ -0,0 +1,2 @@
1
+ name "<%= app %>"
2
+ labels(app: "<%= app %>")
@@ -1,7 +1,10 @@
1
- name "<%= app %>-web"
1
+ name "web"
2
2
  labels(role: "web")
3
3
 
4
4
  replicas 1
5
5
  image built_image # IE: user/<%= app %>:kubes-2020-06-13T19-55-16-43afc6e
6
6
 
7
+ # revisionHistoryLimit 1 # uncomment to reduce old ReplicaSets, default is 10 https://bit.ly/3hqrzyP
8
+ # maxUnavailable 25
9
+
7
10
  # More docs: kubes.guru/docs/dsl/deployment/
@@ -1,8 +1,8 @@
1
- name "<%= app %>-web"
1
+ name "web"
2
2
  labels(role: "web")
3
3
 
4
4
  # Optional since default port is 80
5
5
  # port 80
6
- # targetPort 80
6
+ targetPort dockerfile_port # expose port in Dockerfile
7
7
 
8
8
  # More docs: kubes.guru/docs/dsl/service/
@@ -1,2 +1,2 @@
1
1
  metadata:
2
- namespace: default
2
+ namespace: <%= app %>
@@ -0,0 +1,6 @@
1
+ apiVersion: v1
2
+ kind: Namespace
3
+ metadata:
4
+ name: <%= app %>
5
+ labels:
6
+ app: <%= app %>
@@ -1,7 +1,7 @@
1
1
  apiVersion: apps/v1
2
2
  kind: Deployment
3
3
  metadata:
4
- name: <%= app %>-web
4
+ name: web
5
5
  labels:
6
6
  role: web
7
7
  spec:
@@ -9,16 +9,11 @@ spec:
9
9
  selector:
10
10
  matchLabels:
11
11
  role: web
12
- strategy:
13
- rollingUpdate:
14
- maxSurge: 25
15
- maxUnavailable: 25
16
- type: RollingUpdate
17
12
  template:
18
13
  metadata:
19
14
  labels:
20
15
  role: web
21
16
  spec:
22
17
  containers:
23
- - name: <%= app %>-web
18
+ - name: web
24
19
  image: <%%= built_image %>
@@ -1,14 +1,14 @@
1
1
  apiVersion: v1
2
2
  kind: Service
3
3
  metadata:
4
- name: <%= app %>-web
4
+ name: web
5
5
  labels:
6
6
  role: web
7
7
  spec:
8
8
  ports:
9
9
  - port: 80
10
10
  protocol: TCP
11
- targetPort: 80
11
+ targetPort: <%%= dockerfile_port %>
12
12
  selector:
13
13
  role: web
14
14
  type: ClusterIP
@@ -1,3 +1,3 @@
1
1
  name "demo-web-allow-tester"
2
2
  matchLabels(role: "web")
3
- fromMatchLabels(run: "tester")
3
+ fromPod(run: "tester")
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kubes
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tung Nguyen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-07-16 00:00:00.000000000 Z
11
+ date: 2020-07-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -214,9 +214,11 @@ executables:
214
214
  extensions: []
215
215
  extra_rdoc_files: []
216
216
  files:
217
+ - ".dockerignore"
217
218
  - ".gitignore"
218
219
  - ".rspec"
219
220
  - CHANGELOG.md
221
+ - Dockerfile
220
222
  - Gemfile
221
223
  - Guardfile
222
224
  - LICENSE.txt
@@ -231,7 +233,9 @@ files:
231
233
  - docs/Rakefile
232
234
  - docs/_config.yml
233
235
  - docs/_docs/auto-context.md
236
+ - docs/_docs/ci/cloudbuild.md
234
237
  - docs/_docs/config.md
238
+ - docs/_docs/config/build-strategy.md
235
239
  - docs/_docs/config/docker.md
236
240
  - docs/_docs/config/env.md
237
241
  - docs/_docs/config/kubectl.md
@@ -510,10 +514,17 @@ files:
510
514
  - lib/kubes/completer/script.sh
511
515
  - lib/kubes/config.rb
512
516
  - lib/kubes/core.rb
517
+ - lib/kubes/docker.rb
513
518
  - lib/kubes/docker/args/default.rb
514
- - lib/kubes/docker/base.rb
515
- - lib/kubes/docker/build.rb
516
- - lib/kubes/docker/push.rb
519
+ - lib/kubes/docker/strategy/build/base.rb
520
+ - lib/kubes/docker/strategy/build/docker.rb
521
+ - lib/kubes/docker/strategy/build/gcloud.rb
522
+ - lib/kubes/docker/strategy/hooks.rb
523
+ - lib/kubes/docker/strategy/image_name.rb
524
+ - lib/kubes/docker/strategy/push/base.rb
525
+ - lib/kubes/docker/strategy/push/docker.rb
526
+ - lib/kubes/docker/strategy/push/gcloud.rb
527
+ - lib/kubes/docker/strategy/utils.rb
517
528
  - lib/kubes/hooks/builder.rb
518
529
  - lib/kubes/hooks/dsl.rb
519
530
  - lib/kubes/kubectl.rb
@@ -536,12 +547,14 @@ files:
536
547
  - lib/templates/base/.kubes/config/env/prod.rb
537
548
  - lib/templates/docker/Dockerfile
538
549
  - lib/templates/dsl/.kubes/resources/base/all.rb.tt
539
- - lib/templates/dsl/.kubes/resources/web/deployment.rb.tt
550
+ - lib/templates/dsl/.kubes/resources/shared/namespace.rb.tt
551
+ - lib/templates/dsl/.kubes/resources/web/deployment.rb
540
552
  - lib/templates/dsl/.kubes/resources/web/deployment/dev.rb
541
553
  - lib/templates/dsl/.kubes/resources/web/deployment/prod.rb
542
- - lib/templates/dsl/.kubes/resources/web/service.rb.tt
554
+ - lib/templates/dsl/.kubes/resources/web/service.rb
543
555
  - lib/templates/yaml/.kubes/resources/base/all.yaml.tt
544
556
  - lib/templates/yaml/.kubes/resources/base/deployment.yaml.tt
557
+ - lib/templates/yaml/.kubes/resources/shared/namespace.yaml.tt
545
558
  - lib/templates/yaml/.kubes/resources/web/deployment.yaml.tt
546
559
  - lib/templates/yaml/.kubes/resources/web/deployment/dev.yaml
547
560
  - lib/templates/yaml/.kubes/resources/web/deployment/prod.yaml
@@ -1,33 +0,0 @@
1
- require 'open4'
2
-
3
- module Kubes::Docker
4
- class Build < Base
5
- def run
6
- reserve_image_name
7
- build
8
- store_image_name
9
- end
10
-
11
- def build
12
- # Dockerfile is also used in args/default.rb, will have to combine if Dockerfile is made configurable
13
- unless File.exist?("Dockerfile")
14
- logger.error "ERROR: The Dockerfile does not exist. Cannot build the docker image without a Dockerfile".color(:red)
15
- exit 1
16
- end
17
- params = args.flatten.join(' ')
18
- command = "docker build #{params}"
19
- run_hooks "build" do
20
- # sh(command)
21
- spawn(command)
22
- end
23
- end
24
-
25
- def spawn(command, stdin: '', stdout: STDOUT, stderr: STDERR)
26
- Open4::spawn(
27
- command,
28
- stdin: stdin,
29
- stdout: stdout,
30
- stderr: stderr)
31
- end
32
- end
33
- end