kontena-mortar 0.1.0 → 0.2.0.pre1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.drone.yml +18 -2
- data/.travis.yml +28 -0
- data/Dockerfile +4 -6
- data/Gemfile.lock +11 -3
- data/README.md +112 -4
- data/bin/mortar +1 -1
- data/build/drone/create_release.sh +28 -0
- data/build/drone/ubuntu_xenial.sh +24 -0
- data/build/travis/macos.sh +24 -0
- data/examples/basic/deployment.yml +18 -0
- data/examples/basic/service.yml +10 -0
- data/examples/force-deployment/deployment.yml.erb +27 -0
- data/examples/overlays/echo-metal.yml +35 -0
- data/examples/overlays/foo/pod.yml.erb +14 -0
- data/examples/overlays/partial/echo.yml +8 -0
- data/examples/overlays/prod/pod.yml +13 -0
- data/examples/overlays/prod/svc.yml +14 -0
- data/examples/templates/env_vars/pod.yml.erb +13 -0
- data/examples/templates/variables/loops.yml.erb +19 -0
- data/examples/templates/variables/pod-vars.yml.erb +15 -0
- data/kontena-mortar.gemspec +2 -1
- data/kontena-mortar.png +0 -0
- data/lib/extensions/recursive_open_struct/each.rb +12 -0
- data/lib/mortar/command.rb +1 -155
- data/lib/mortar/fire_command.rb +108 -0
- data/lib/mortar/mixins/client_helper.rb +57 -0
- data/lib/mortar/{resource_helper.rb → mixins/resource_helper.rb} +0 -0
- data/lib/mortar/mixins/tty_helper.rb +8 -0
- data/lib/mortar/root_command.rb +20 -0
- data/lib/mortar/version.rb +1 -1
- data/lib/mortar/yank_command.rb +40 -0
- data/lib/mortar.rb +4 -1
- metadata +43 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bea90dd703d70062d7fdc1d1fb6df91c4d58db52caa8e2e106734a82b713cb8b
|
4
|
+
data.tar.gz: 50ff8a0d860da001ad116b1037424aad567dbd01f82499fc2f81c0418fcf29c7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c0faca7f612c4924b7dc175d3faf0c7bb11a7dbf018473043a60c6a4152f3ffa0be598fc1606cb7d5188b8f34b9f0102c709797422ddb677bd421f853d838c8f
|
7
|
+
data.tar.gz: 3a7dedfd64a08550a725e12cbc27fcdee3ac15bc3658312b2aca604434754acf46c082fafb395dad599c68856f9ecab439d433496cde925c65074ebfb48bec56
|
data/.drone.yml
CHANGED
@@ -3,8 +3,7 @@ pipeline:
|
|
3
3
|
image: ruby:2.4
|
4
4
|
commands:
|
5
5
|
- bundle install --path bundler
|
6
|
-
#
|
7
|
-
# - bundle exec rspec spec/ && bundle exec rubocop --fail-level A -S --format c --parallel
|
6
|
+
- bundle exec rspec spec/ # && bundle exec rubocop --fail-level A -S --format c --parallel
|
8
7
|
docker_latest:
|
9
8
|
registry: quay.io
|
10
9
|
image: plugins/docker
|
@@ -35,3 +34,20 @@ pipeline:
|
|
35
34
|
- gem push *.gem
|
36
35
|
when:
|
37
36
|
event: ['tag']
|
37
|
+
|
38
|
+
create_gh_release:
|
39
|
+
image: ubuntu:xenial
|
40
|
+
secrets: [ github_token ]
|
41
|
+
commands:
|
42
|
+
- ./build/drone/create_release.sh
|
43
|
+
when:
|
44
|
+
event: tag
|
45
|
+
build_xenial:
|
46
|
+
image: ubuntu:xenial
|
47
|
+
secrets: [ github_token ]
|
48
|
+
environment:
|
49
|
+
- CPPFLAGS=-P
|
50
|
+
commands:
|
51
|
+
- ./build/drone/ubuntu_xenial.sh
|
52
|
+
when:
|
53
|
+
event: tag
|
data/.travis.yml
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
language: ruby
|
2
|
+
sudo: required
|
3
|
+
cache: bundler
|
4
|
+
bundler_args: --without development
|
5
|
+
env:
|
6
|
+
global:
|
7
|
+
- secure: "AX0y/vETBJ4C93/RWgTZNFwlm8r+4b0cWExOa3G4NBvxc3x1PBjA9sD7LOezUxMCaOuTM1GF+vpXupreeZtdU6mUqQNJSsOH5sWivPfQwCmxbhODW/CGhlhKZT0pTJQ2QhUbp6zXeLfQ3WJT4X4VH2NP5zkfJ7Q0hO7AJqqty/+mAZLbtaBkw1eKhwWPx1t3UQx9zY07V2WsJQCmj9O/bdMyoa3uoTvSahzvAQsY/1XQ6OMZrVvt7JGoFjEVLNnttT3at3HvG3Izwb8u+ftrCr+0u6V9tUPAH+1WHJgP1fYrysU2n+HwhvGYlkl3TYt0wxP9ccz18NiFGf3SOf+OSBQJ11cQ6RJ7R6Qo/RLpW2AffjYW881d32pORbVsEpj8vBvElfJKbl0rT4IgIRJxxCuZnqVbX+8szma9EAmltGbtNdyuX4WxARZ3XNlFONacX5mnubRZDruYijNPzv3tCb6KBaRV5yfg8dhMPjOf6r0i8r0+9IFRsfszVMSxJhrnXlhtaYn7OikqBDOSiCa/VeSBb09fl/klnTCpCHFRICYgWqO8vf1jWvXLuKtHA7E3Ah4CJTkirY4eFwLMEN2kJ6g28OudWMU/urL4/rRb4LpzlDySy9KFA8f1/+7A/mzLDv7Iket2ig6/Pa7ymnYSlmypzVZTvcpJr0EfK+hmr6E="
|
8
|
+
stages:
|
9
|
+
- name: publish binary
|
10
|
+
if: tag IS present
|
11
|
+
jobs:
|
12
|
+
include:
|
13
|
+
- stage: publish binary
|
14
|
+
script: ./build/travis/macos.sh
|
15
|
+
rvm: 2.4
|
16
|
+
os: osx
|
17
|
+
deploy:
|
18
|
+
provider: s3
|
19
|
+
access_key_id:
|
20
|
+
secure: "OHjLg4bzJBUdwmw42XK5s/+5tHUy7SO32/NzV5qCETIw+lr0lEhHIUeGUDGEqsMKvB3X1rIyFhhYJcRUCkJHfDUM2uRyIxYl/HUNNHCnZttwBHsn517Wt8sSzx5mSHuqXl54hoI47vvx0yfKrvW70/AF0aNufEde5tQePzsgghZ0FIPKx29CiG0QAufTgJ3B3tXJtDywDXO6kyQmmpjSTO+Rne8YEx4MvyoGH1DhHiiSsggSMrYUy80mZP967AvQ6cCQNS7d9A1ThNjJVNGQ9jzTGW8vWRsvI1Y5583sWwAwVbKSYtcaO2t5IC1q62PnYu9xVyy6D5QZ4uJ4jQk8at00348nj059CosNEE9IdqRaTJi5TIiX9H1nU8y3P/c/2dYpsQIKch0Ji/cQhl4RCe+QQuOpCzggElf8GeD/tg9GJFhX+uPPWFJMl4zvrH5EascRm+PHJsr7UFL0Lv4Q0x85qdCa/0Oh1XA+f+WaLpSkUUiLUUB27+2dLupD3VyuSZ0IferiDHHgIG0teXoSvI6hgSBg85ZYZKls72seTuGG0icrn+U/iz+7ywtaaS5yVmrelUiYq4ElZr3N9SPaWUxUGXo734B60AIJ9dPQQJY8e+TJ2jjX3OCAd//Z3Kh2+O+nbcHUUMY4OfUVp4wcRy2LKlNqPC5DevZij2uVmKM="
|
21
|
+
secret_access_key:
|
22
|
+
secure: "HCnQTlTJ3jo4oX2ZLXZUUWHOL7yiV/z2dVNTmiQYGJ8Xsf34zLnwRvPTymq4nA7elCmO0J6G2ub1wqBLZqyYHhbhI//9txPpRJmgFf7C3R0c9j5HRG2lxRJ8PNHuOzT5e2Zx1Aq9Aawy2+zXTuNMnTF0gtXg2tO3oHzs2h99mk5qeoLDAbu1HUd+W7ymalbhw+GH3D6X4mHuv/AUowOJuieIMpg/FPvu0/SXh4/KpSV54hlfSDYIqaBlMDxdAJsoJi/tKBegNMkLeXyaFf9PYF6U83P8RABdBkhinatN0b6EJB21mmaRkfVam4gNhEgB+SobZVelmLLAsTZU9kEkt2V4zBgUYUbNI32ZXMhMFsOZtPfInbGAzqZPmKGRh39yFnN92uQjxWJXocGFrk43K3d2lviAntP05+xPpBjO4CDXuC8mqyRZf6vg/Cysu3OuxrUGMru0EHePG6DZDcH8yNq7GcBbarA5+w+hupnfHD8SoRtnSuyPdyPsjGb25vikkgeLN8J8d2FxcUH9NBgeBJXhMcXCKCxmIgCcMtJ1NElip6MktTYMl2nkxDmgpPljUG0QL95fVq88jwWhyxTvpASJvUSDbq0AUWNP5xJ4R+4vlWkSkVrtLhn4IaJ4ou6PATmgzyaw+0EG4JeAT2TfP8z6ILv5NNb/4YThwg08fVA="
|
23
|
+
bucket: "pharos-cluster-binaries"
|
24
|
+
region: "eu-west-1"
|
25
|
+
local-dir: upload
|
26
|
+
skip_cleanup: true
|
27
|
+
on:
|
28
|
+
all_branches: true
|
data/Dockerfile
CHANGED
@@ -2,14 +2,12 @@ FROM ruby:2.5-alpine as build
|
|
2
2
|
|
3
3
|
ADD . /src
|
4
4
|
|
5
|
-
RUN apk --update add git && \
|
6
|
-
cd /src ; gem build kontena-mortar.gemspec
|
5
|
+
RUN apk --update add git build-base && \
|
6
|
+
cd /src ; gem build kontena-mortar.gemspec && \
|
7
|
+
gem install *.gem
|
7
8
|
|
8
9
|
FROM ruby:2.5-alpine
|
9
10
|
|
10
|
-
COPY --from=build /
|
11
|
-
|
12
|
-
RUN gem install /tmp/*.gem && \
|
13
|
-
rm -f /tmp/*.gem
|
11
|
+
COPY --from=build /usr/local/bundle /usr/local/bundle
|
14
12
|
|
15
13
|
ENTRYPOINT [ "/usr/local/bundle/bin/mortar" ]
|
data/Gemfile.lock
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
kontena-mortar (0.
|
4
|
+
kontena-mortar (0.2.0.pre1)
|
5
5
|
clamp (~> 1.3)
|
6
6
|
deep_merge (~> 1.2)
|
7
|
-
k8s-client (~> 0.
|
7
|
+
k8s-client (~> 0.4.1)
|
8
|
+
pastel (~> 0.7.2)
|
8
9
|
rouge (~> 3.2)
|
9
10
|
|
10
11
|
GEM
|
@@ -39,13 +40,19 @@ GEM
|
|
39
40
|
dry-equalizer (~> 0.2)
|
40
41
|
dry-inflector (~> 0.1, >= 0.1.2)
|
41
42
|
dry-logic (~> 0.4, >= 0.4.2)
|
43
|
+
equatable (0.5.0)
|
42
44
|
excon (0.62.0)
|
45
|
+
hashdiff (0.3.7)
|
43
46
|
ice_nine (0.11.2)
|
44
|
-
k8s-client (0.
|
47
|
+
k8s-client (0.4.1)
|
45
48
|
deep_merge (~> 1.2.1)
|
46
49
|
dry-struct (~> 0.5.0)
|
47
50
|
excon (~> 0.62.0)
|
51
|
+
hashdiff (~> 0.3.7)
|
48
52
|
recursive-open-struct (~> 1.1.0)
|
53
|
+
pastel (0.7.2)
|
54
|
+
equatable (~> 0.5.0)
|
55
|
+
tty-color (~> 0.4.0)
|
49
56
|
rake (10.5.0)
|
50
57
|
recursive-open-struct (1.1.0)
|
51
58
|
rouge (3.2.1)
|
@@ -62,6 +69,7 @@ GEM
|
|
62
69
|
diff-lcs (>= 1.2.0, < 2.0)
|
63
70
|
rspec-support (~> 3.8.0)
|
64
71
|
rspec-support (3.8.0)
|
72
|
+
tty-color (0.4.3)
|
65
73
|
|
66
74
|
PLATFORMS
|
67
75
|
ruby
|
data/README.md
CHANGED
@@ -1,6 +1,16 @@
|
|
1
1
|
# Kontena Mortar
|
2
2
|
|
3
|
-
|
3
|
+
![Mortar - Manifest shooter for Kubernetes](kontena-mortar.png)
|
4
|
+
|
5
|
+
Mortar is a tool to easily handle a complex set of Kubernetes resources. Using `kubectl apply -f some_folder/` is pretty straightforward for simple cases, but often, especially in CI/CD pipelines things get complex. Then on the otherhand, writing everything in Helm charts is way too complex.
|
6
|
+
|
7
|
+
While we were developing [Kontena Pharos](https://kontena.io/pharos) Kubernetes distro and tooling around it, we soon realized that we really want to manage sets of resources as a single unit. This thinking got even stronger while we were transitioning many of our production solutions to run on top of Kubernetes. As this is a common problem for all Kubernetes users, Mortar was born.
|
8
|
+
|
9
|
+
## Features
|
10
|
+
|
11
|
+
- [Management of sets of resources as a single unit](#shots)
|
12
|
+
- [Simple templating](#templating)
|
13
|
+
- [Overlays](#overlays)
|
4
14
|
|
5
15
|
## Installation
|
6
16
|
|
@@ -12,6 +22,8 @@ Docker:
|
|
12
22
|
|
13
23
|
`$ docker pull quay.io/kontena/mortar:latest`
|
14
24
|
|
25
|
+
We will be working on also to support binary installation method in near future.
|
26
|
+
|
15
27
|
## Usage
|
16
28
|
|
17
29
|
### Configuration
|
@@ -21,13 +33,19 @@ By default mortar looks for if file `~/.kube/config` exists and uses it as the c
|
|
21
33
|
For CI/CD use mortar also understands following environment variables:
|
22
34
|
|
23
35
|
- `KUBE_SERVER`: kubernetes api server address, for example `https://10.10.10.10:6443`
|
24
|
-
- `KUBE_TOKEN`: service account token
|
36
|
+
- `KUBE_TOKEN`: service account token (base64 encoded)
|
25
37
|
- `KUBE_CA`: kubernetes CA certificate (base64 encoded)
|
26
38
|
|
27
39
|
### Deploying k8s yaml manifests
|
28
40
|
|
29
41
|
```
|
30
|
-
$ mortar <
|
42
|
+
$ mortar fire [options] <src-folder> <deployment-name>
|
43
|
+
```
|
44
|
+
|
45
|
+
### Removing a deployment
|
46
|
+
|
47
|
+
```
|
48
|
+
$ mortar yank [options] <deployment-name>
|
31
49
|
```
|
32
50
|
|
33
51
|
### Docker image
|
@@ -46,6 +64,96 @@ pipeline:
|
|
46
64
|
|
47
65
|
```
|
48
66
|
|
67
|
+
## Shots
|
68
|
+
|
69
|
+
Mortar manages a set of resources as a single unit, we call them *shots*. A shot can have as many resources as your application needs, there's no limit to that. Much like you'd do with `kubectl apply -f my_dir/`, but Mortar actually injects information into the resources it shoots into your Kubernetes cluster. This added information, labels and annotations, will be used later on by Mortar itself or can be used with `kubectl` too. This allows the management of many resources as a single application.
|
70
|
+
|
71
|
+
Most importantly, Mortar is able to use this information when re-shooting your applications. One of the most difficult parts when using plain `kubectl apply ...` approach is the fact that it's super easy to leave behind some lingering resources. Say you have some `deployments` and a `service` in your application, each defined in their own `yaml` file. Now you remove the service and re-apply with `kubectl apply -f my_resources/`. The service will live on in your cluster. With Mortar, you don't have to worry. With the extra labels and annotations Mortar injects into the resources, it's also able to automatically prune the "un-necessary" resources from the cluster. The automatic pruning is done with `--prune` option.
|
72
|
+
|
73
|
+
See basic example [here](/examples/basic).
|
74
|
+
|
75
|
+
## Overlays
|
76
|
+
|
77
|
+
One of the most powerful features of Mortar is it's ability to support *overlays*. An overlay is a variant of the set of resources you are managing. A variant might be for example the same application running on many different environments like production, test, QA an so on. A variant might also be a separate application "instance" for each customer. Or what ever the need is. Overlays in Mortar are inspired by [kustomize](https://github.com/kubernetes-sigs/kustomize).
|
78
|
+
|
79
|
+
Given a folder & file structure like:
|
80
|
+
```
|
81
|
+
echoservice-metallb/
|
82
|
+
├── echo-metal.yml
|
83
|
+
├── foo
|
84
|
+
│ └── pod.yml.erb
|
85
|
+
└── prod
|
86
|
+
├── pod.yml
|
87
|
+
└── svc.yml
|
88
|
+
```
|
89
|
+
|
90
|
+
where overlays (`prod` & `foo`) contain same resources as the base folder, mortar now merges all resources together. Merging is done in the order overlays are given in the command. Resources are considered to be the same resource if all of these match: `kind`, `apiVersion`, `metadata.name` and `metadata.namespace`.
|
91
|
+
|
92
|
+
If there are new resources in the overlay dirs, they are taken into the shot as-is.
|
93
|
+
|
94
|
+
You'd select overlays taken into processing with `--overlay option`.
|
95
|
+
|
96
|
+
**Note:** Overlays are taken in in the order defined, so make sure you define them in correct order.
|
97
|
+
|
98
|
+
The resources in the overlays do not have to be complete, it's enough that the "identifying" fields are the same.
|
99
|
+
|
100
|
+
See example of overlays [here](/examples/overlays).
|
101
|
+
|
102
|
+
## Templating
|
103
|
+
|
104
|
+
Mortar also support templating for the resource definitons. The templating language used is [ERB](https://en.wikipedia.org/wiki/ERuby). It's pretty simple templating language but yet powerful enough for Kubernetes resource templating.
|
105
|
+
|
106
|
+
Mortar automatically processes the resource definition as a template if the filename is either `.yml.erb` or `.yaml.erb`.
|
107
|
+
|
108
|
+
There are two ways to introduce variables into the templating.
|
109
|
+
|
110
|
+
See examples at [examples/templates](examples/templates).
|
111
|
+
|
112
|
+
### Environment variables
|
113
|
+
|
114
|
+
As for any process, environment variables are also available for Mortar during template processing.
|
115
|
+
|
116
|
+
```
|
117
|
+
kind: Pod
|
118
|
+
apiVersion: v1
|
119
|
+
metadata:
|
120
|
+
name: nginx
|
121
|
+
labels:
|
122
|
+
name: nginx
|
123
|
+
namespace: default
|
124
|
+
spec:
|
125
|
+
containers:
|
126
|
+
- name: nginx
|
127
|
+
image: nginx:<%= ENV["NGINX_VERSION"] || "latest" %>
|
128
|
+
ports:
|
129
|
+
- containerPort: 80
|
130
|
+
```
|
131
|
+
|
132
|
+
### Variables via options
|
133
|
+
|
134
|
+
Another option to use variables is via command-line options. Use `mortar --var foo=bar my-app resources/`.
|
135
|
+
|
136
|
+
Each of the variables defined will be available in the template via `var.<variable name>`.
|
137
|
+
|
138
|
+
```
|
139
|
+
kind: Pod
|
140
|
+
apiVersion: v1
|
141
|
+
metadata:
|
142
|
+
name: nginx
|
143
|
+
labels:
|
144
|
+
name: nginx
|
145
|
+
namespace: default
|
146
|
+
spec:
|
147
|
+
containers:
|
148
|
+
- name: nginx
|
149
|
+
image: nginx:latest
|
150
|
+
ports:
|
151
|
+
- containerPort: <%= port.number %>
|
152
|
+
name: <%= port.name %>
|
153
|
+
```
|
154
|
+
|
155
|
+
You could shoot this resource with `mortar --var port.name=some-port --var port.number=80 my-app resources/pod.yml.erb`
|
156
|
+
|
49
157
|
|
50
158
|
## Contributing
|
51
159
|
|
@@ -59,4 +167,4 @@ Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
|
59
167
|
|
60
168
|
http://www.apache.org/licenses/LICENSE-2.0
|
61
169
|
|
62
|
-
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.
|
170
|
+
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.
|
data/bin/mortar
CHANGED
@@ -0,0 +1,28 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
set -ue
|
4
|
+
|
5
|
+
apt-get update -y
|
6
|
+
apt-get install -y -q curl bzip2
|
7
|
+
|
8
|
+
# ship to github
|
9
|
+
curl -sL https://github.com/aktau/github-release/releases/download/v0.7.2/linux-amd64-github-release.tar.bz2 | tar -xjO > /usr/local/bin/github-release
|
10
|
+
chmod +x /usr/local/bin/github-release
|
11
|
+
|
12
|
+
if [[ $DRONE_TAG =~ .+-.+ ]]; then
|
13
|
+
/usr/local/bin/github-release release \
|
14
|
+
--user kontena \
|
15
|
+
--repo mortar \
|
16
|
+
--tag $DRONE_TAG \
|
17
|
+
--name $DRONE_TAG \
|
18
|
+
--description "Pre-release, only for testing" \
|
19
|
+
--draft \
|
20
|
+
--pre-release
|
21
|
+
else
|
22
|
+
/usr/local/bin/github-release release \
|
23
|
+
--user kontena \
|
24
|
+
--repo mortar \
|
25
|
+
--draft \
|
26
|
+
--tag $DRONE_TAG \
|
27
|
+
--name $DRONE_TAG
|
28
|
+
fi
|
@@ -0,0 +1,24 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
|
3
|
+
set -ue
|
4
|
+
|
5
|
+
# build binary
|
6
|
+
apt-get update -y
|
7
|
+
apt-get install -y -q squashfs-tools build-essential ruby bison ruby-dev git-core texinfo curl
|
8
|
+
curl -sL https://dl.bintray.com/kontena/ruby-packer/0.5.0-dev/rubyc-linux-amd64.gz | gunzip > /usr/local/bin/rubyc
|
9
|
+
chmod +x /usr/local/bin/rubyc
|
10
|
+
gem install bundler
|
11
|
+
version=${DRONE_TAG#"v"}
|
12
|
+
package="mortar-linux-amd64-${version}"
|
13
|
+
rubyc -o $package mortar
|
14
|
+
./$package version
|
15
|
+
|
16
|
+
# ship to github
|
17
|
+
curl -sL https://github.com/aktau/github-release/releases/download/v0.7.2/linux-amd64-github-release.tar.bz2 | tar -xjO > /usr/local/bin/github-release
|
18
|
+
chmod +x /usr/local/bin/github-release
|
19
|
+
/usr/local/bin/github-release upload \
|
20
|
+
--user kontena \
|
21
|
+
--repo mortar \
|
22
|
+
--tag $DRONE_TAG \
|
23
|
+
--name $package \
|
24
|
+
--file ./$package
|
@@ -0,0 +1,24 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
|
3
|
+
set -ue
|
4
|
+
|
5
|
+
brew install squashfs
|
6
|
+
curl -sL https://dl.bintray.com/kontena/ruby-packer/0.5.0-dev/rubyc-darwin-amd64.gz | gunzip > /usr/local/bin/rubyc
|
7
|
+
chmod +x /usr/local/bin/rubyc
|
8
|
+
version=${TRAVIS_TAG#"v"}
|
9
|
+
package="mortar-darwin-amd64-${version}"
|
10
|
+
rubyc -o $package mortar
|
11
|
+
./$package version
|
12
|
+
|
13
|
+
# ship to github
|
14
|
+
curl -sL https://github.com/aktau/github-release/releases/download/v0.7.2/darwin-amd64-github-release.tar.bz2 | tar -xjO > /usr/local/bin/github-release
|
15
|
+
chmod +x /usr/local/bin/github-release
|
16
|
+
/usr/local/bin/github-release upload \
|
17
|
+
--user kontena \
|
18
|
+
--repo mortar \
|
19
|
+
--tag $TRAVIS_TAG \
|
20
|
+
--name $package \
|
21
|
+
--file ./$package
|
22
|
+
|
23
|
+
mkdir -p upload
|
24
|
+
mv $package upload/
|
@@ -0,0 +1,18 @@
|
|
1
|
+
apiVersion: apps/v1
|
2
|
+
kind: Deployment
|
3
|
+
metadata:
|
4
|
+
name: myapp
|
5
|
+
spec:
|
6
|
+
selector:
|
7
|
+
matchLabels:
|
8
|
+
app: myapp
|
9
|
+
template:
|
10
|
+
metadata:
|
11
|
+
labels:
|
12
|
+
app: myapp
|
13
|
+
spec:
|
14
|
+
containers:
|
15
|
+
- name: myapp
|
16
|
+
image: nginx:latest
|
17
|
+
ports:
|
18
|
+
- containerPort: 80
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# An dynamic annotation can be used to force Kubernetes to deploy pods.
|
2
|
+
# In this example mortar will set DRONE_BUILD_NUMBER environment variable as a value of 'build' annotation.
|
3
|
+
# Basically annotation can be, for example, datetime, commit sha or any unique value
|
4
|
+
apiVersion: apps/v1
|
5
|
+
kind: Deployment
|
6
|
+
metadata:
|
7
|
+
name: nginx
|
8
|
+
labels:
|
9
|
+
app: nginx
|
10
|
+
spec:
|
11
|
+
selector:
|
12
|
+
matchLabels:
|
13
|
+
app: nginx
|
14
|
+
strategy:
|
15
|
+
template:
|
16
|
+
metadata:
|
17
|
+
labels:
|
18
|
+
app: nginx
|
19
|
+
annotations:
|
20
|
+
build: "<%= ENV['DRONE_BUILD_NUMBER'] %>"
|
21
|
+
spec:
|
22
|
+
containers:
|
23
|
+
- image: docker.io/nginx:alpine
|
24
|
+
imagePullPolicy: Always
|
25
|
+
name: nginx
|
26
|
+
ports:
|
27
|
+
- containerPort: 80
|
@@ -0,0 +1,35 @@
|
|
1
|
+
---
|
2
|
+
apiVersion: extensions/v1beta1
|
3
|
+
kind: Deployment
|
4
|
+
metadata:
|
5
|
+
name: echoserver
|
6
|
+
namespace: default
|
7
|
+
spec:
|
8
|
+
replicas: 1
|
9
|
+
template:
|
10
|
+
metadata:
|
11
|
+
labels:
|
12
|
+
app: echoserver
|
13
|
+
spec:
|
14
|
+
containers:
|
15
|
+
- image: gcr.io/google_containers/echoserver:1.0
|
16
|
+
imagePullPolicy: Always
|
17
|
+
name: echoserver
|
18
|
+
ports:
|
19
|
+
- containerPort: 8080
|
20
|
+
---
|
21
|
+
apiVersion: v1
|
22
|
+
kind: Service
|
23
|
+
metadata:
|
24
|
+
name: echoserver
|
25
|
+
namespace: default
|
26
|
+
annotations:
|
27
|
+
metallb.universe.tf/address-pool: default
|
28
|
+
spec:
|
29
|
+
type: LoadBalancer
|
30
|
+
ports:
|
31
|
+
- port: 80
|
32
|
+
targetPort: 8080
|
33
|
+
protocol: TCP
|
34
|
+
selector:
|
35
|
+
app: echoserver
|
@@ -0,0 +1,19 @@
|
|
1
|
+
kind: Pod
|
2
|
+
apiVersion: v1
|
3
|
+
metadata:
|
4
|
+
name: nginx
|
5
|
+
labels:
|
6
|
+
name: nginx
|
7
|
+
namespace: default
|
8
|
+
spec:
|
9
|
+
containers:
|
10
|
+
- name: nginx
|
11
|
+
image: nginx:latest
|
12
|
+
ports:
|
13
|
+
<%# Easy to loop through some variables with the dotted notation
|
14
|
+
# Run this with example mortar --var port.one=80 --var port.two=8080
|
15
|
+
%>
|
16
|
+
<% var.port.each do |name, number| %>
|
17
|
+
- containerPort: <%= number %>
|
18
|
+
name: <%= name %>
|
19
|
+
<% end %>
|
@@ -0,0 +1,15 @@
|
|
1
|
+
kind: Pod
|
2
|
+
apiVersion: v1
|
3
|
+
metadata:
|
4
|
+
name: nginx
|
5
|
+
labels:
|
6
|
+
name: nginx
|
7
|
+
namespace: default
|
8
|
+
spec:
|
9
|
+
containers:
|
10
|
+
- name: nginx
|
11
|
+
image: nginx:latest
|
12
|
+
ports:
|
13
|
+
<%# Variables can be accessed by the name easily %>
|
14
|
+
- containerPort: <%= port.number %>
|
15
|
+
name: <%= port.name %>
|
data/kontena-mortar.gemspec
CHANGED
@@ -24,9 +24,10 @@ Gem::Specification.new do |spec|
|
|
24
24
|
spec.require_paths = ["lib"]
|
25
25
|
|
26
26
|
spec.add_runtime_dependency "clamp", "~> 1.3"
|
27
|
-
spec.add_runtime_dependency "k8s-client", "~> 0.
|
27
|
+
spec.add_runtime_dependency "k8s-client", "~> 0.4.1"
|
28
28
|
spec.add_runtime_dependency "rouge", "~> 3.2"
|
29
29
|
spec.add_runtime_dependency "deep_merge", "~> 1.2"
|
30
|
+
spec.add_runtime_dependency "pastel", "~> 0.7.2"
|
30
31
|
spec.add_development_dependency "bundler", "~> 1.16"
|
31
32
|
spec.add_development_dependency "rake", "~> 10.0"
|
32
33
|
spec.add_development_dependency "rspec", "~> 3.0"
|
data/kontena-mortar.png
ADDED
Binary file
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Extensions
|
2
|
+
module RecursiveOpenStruct
|
3
|
+
module Each
|
4
|
+
def each(&block)
|
5
|
+
self.to_h.each { |k,v| yield k.to_s,v }
|
6
|
+
end
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
# Monkey-patch the above module into RecursiveOpenStruct
|
12
|
+
RecursiveOpenStruct.include Extensions::RecursiveOpenStruct::Each
|
data/lib/mortar/command.rb
CHANGED
@@ -1,164 +1,10 @@
|
|
1
1
|
require "clamp"
|
2
|
-
require "base64"
|
3
|
-
require_relative "yaml_file"
|
4
|
-
require_relative "resource_helper"
|
5
|
-
|
6
|
-
Clamp.allow_options_after_parameters = true
|
7
2
|
|
8
3
|
module Mortar
|
9
4
|
class Command < Clamp::Command
|
10
|
-
include Mortar::ResourceHelper
|
11
|
-
|
12
|
-
banner "mortar - Kubernetes manifest shooter"
|
13
|
-
|
14
|
-
parameter "NAME", "deployment name"
|
15
|
-
parameter "SRC", "source folder"
|
16
|
-
|
17
|
-
option ["--var"], "VAR", "set template variables", multivalued: true
|
18
|
-
option ["-d", "--debug"], :flag, "debug"
|
19
|
-
option ["--output"], :flag, "only output generated yaml"
|
20
|
-
option ["--prune"], :flag, "automatically delete removed resources"
|
21
|
-
option ['-v', '--version'], :flag, "print mortar version" do
|
22
|
-
puts "mortar #{Mortar::VERSION}"
|
23
|
-
exit 0
|
24
|
-
end
|
25
|
-
option ["--overlay"], "OVERLAY", "overlay dirs", multivalued: true
|
26
|
-
|
27
5
|
LABEL = 'mortar.kontena.io/shot'
|
28
6
|
CHECKSUM_ANNOTATION = 'mortar.kontena.io/shot-checksum'
|
29
7
|
|
30
|
-
|
31
|
-
signal_usage_error("#{src} does not exist") unless File.exist?(src)
|
32
|
-
resources = process_overlays
|
33
|
-
if output?
|
34
|
-
puts resources_output(resources)
|
35
|
-
exit
|
36
|
-
end
|
37
|
-
|
38
|
-
K8s::Stack.new(
|
39
|
-
name, resources,
|
40
|
-
debug: debug?,
|
41
|
-
label: LABEL,
|
42
|
-
checksum_annotation: CHECKSUM_ANNOTATION
|
43
|
-
).apply(client, prune: prune?)
|
44
|
-
|
45
|
-
puts "shot #{name} successfully!" if $stdout.tty?
|
46
|
-
end
|
47
|
-
|
48
|
-
def process_overlays
|
49
|
-
resources = load_resources(src)
|
50
|
-
|
51
|
-
overlay_list.each do |overlay|
|
52
|
-
overlay_resources = from_files(overlay)
|
53
|
-
overlay_resources.each do |overlay_resource|
|
54
|
-
match = false
|
55
|
-
resources = resources.map { |r|
|
56
|
-
if same_resource?(r, overlay_resource)
|
57
|
-
match = true
|
58
|
-
r.merge(overlay_resource.to_hash)
|
59
|
-
else
|
60
|
-
r
|
61
|
-
end
|
62
|
-
}
|
63
|
-
resources << overlay_resource unless match
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
resources
|
68
|
-
end
|
69
|
-
|
70
|
-
# @param resources [Array<K8s::Resource>]
|
71
|
-
# @return [String]
|
72
|
-
def resources_output(resources)
|
73
|
-
yaml = ''
|
74
|
-
resources.each do |resource|
|
75
|
-
yaml << ::YAML.dump(stringify_hash(resource.to_hash))
|
76
|
-
end
|
77
|
-
return yaml unless $stdout.tty?
|
78
|
-
|
79
|
-
lexer = Rouge::Lexers::YAML.new
|
80
|
-
rouge = Rouge::Formatters::Terminal256.new(Rouge::Themes::Github.new)
|
81
|
-
rouge.format(lexer.lex(yaml))
|
82
|
-
end
|
83
|
-
|
84
|
-
# @return [RecursiveOpenStruct]
|
85
|
-
def variables_struct
|
86
|
-
return @variables_struct if @variables_struct
|
87
|
-
|
88
|
-
set_hash = {}
|
89
|
-
var_list.each do |var|
|
90
|
-
k, v = var.split("=", 2)
|
91
|
-
set_hash[k] = v
|
92
|
-
end
|
93
|
-
RecursiveOpenStruct.new(dotted_path_to_hash(set_hash))
|
94
|
-
end
|
95
|
-
|
96
|
-
def dotted_path_to_hash(hash)
|
97
|
-
hash.map do |pkey, pvalue|
|
98
|
-
pkey.to_s.split(".").reverse.inject(pvalue) do |value, key|
|
99
|
-
{key.to_sym => value}
|
100
|
-
end
|
101
|
-
end.inject(&:deep_merge)
|
102
|
-
end
|
103
|
-
|
104
|
-
# @return [K8s::Client]
|
105
|
-
def client
|
106
|
-
return @client if @client
|
107
|
-
|
108
|
-
if ENV['KUBE_TOKEN'] && ENV['KUBE_CA'] && ENV['KUBE_SERVER']
|
109
|
-
@client = K8s::Client.new(K8s::Transport.config(build_kubeconfig_from_env))
|
110
|
-
elsif ENV['KUBECONFIG']
|
111
|
-
@client = K8s::Client.config(K8s::Config.load_file(ENV['KUBECONFIG']))
|
112
|
-
elsif File.exist?(File.join(Dir.home, '.kube', 'config'))
|
113
|
-
@client = K8s::Client.config(K8s::Config.load_file(File.join(Dir.home, '.kube', 'config')))
|
114
|
-
else
|
115
|
-
@client = K8s::Client.in_cluster_config
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
# @return [K8s::Config]
|
120
|
-
def build_kubeconfig_from_env
|
121
|
-
token = ENV['KUBE_TOKEN']
|
122
|
-
begin
|
123
|
-
token = Base64.strict_decode64(token)
|
124
|
-
rescue ArgumentError # raised if token is not base64 encoded
|
125
|
-
end
|
126
|
-
K8s::Config.new(
|
127
|
-
clusters: [
|
128
|
-
{
|
129
|
-
name: 'kubernetes',
|
130
|
-
cluster: {
|
131
|
-
server: ENV['KUBE_SERVER'],
|
132
|
-
certificate_authority_data: ENV['KUBE_CA']
|
133
|
-
}
|
134
|
-
}
|
135
|
-
],
|
136
|
-
users: [
|
137
|
-
{
|
138
|
-
name: 'mortar',
|
139
|
-
user: {
|
140
|
-
token: token
|
141
|
-
}
|
142
|
-
}
|
143
|
-
],
|
144
|
-
contexts: [
|
145
|
-
{
|
146
|
-
name: 'mortar',
|
147
|
-
context: {
|
148
|
-
cluster: 'kubernetes',
|
149
|
-
user: 'mortar'
|
150
|
-
}
|
151
|
-
}
|
152
|
-
],
|
153
|
-
preferences: {},
|
154
|
-
current_context: 'mortar'
|
155
|
-
)
|
156
|
-
end
|
157
|
-
|
158
|
-
# Stringifies all hash keys
|
159
|
-
# @return [Hash]
|
160
|
-
def stringify_hash(hash)
|
161
|
-
JSON.load(JSON.dump(hash))
|
162
|
-
end
|
8
|
+
option ["-d", "--debug"], :flag, "debug"
|
163
9
|
end
|
164
10
|
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
require "base64"
|
2
|
+
require_relative "command"
|
3
|
+
require_relative "yaml_file"
|
4
|
+
require_relative "mixins/resource_helper"
|
5
|
+
require_relative "mixins/client_helper"
|
6
|
+
require_relative "mixins/tty_helper"
|
7
|
+
|
8
|
+
module Mortar
|
9
|
+
class FireCommand < Mortar::Command
|
10
|
+
include Mortar::ResourceHelper
|
11
|
+
include Mortar::ClientHelper
|
12
|
+
include Mortar::TTYHelper
|
13
|
+
|
14
|
+
parameter "SRC", "source file or directory"
|
15
|
+
parameter "NAME", "deployment name"
|
16
|
+
|
17
|
+
option ["--var"], "VAR", "set template variables", multivalued: true
|
18
|
+
option ["--output"], :flag, "only output generated yaml"
|
19
|
+
option ["--prune"], :flag, "automatically delete removed resources"
|
20
|
+
option ["--overlay"], "OVERLAY", "overlay dirs", multivalued: true
|
21
|
+
|
22
|
+
def execute
|
23
|
+
signal_usage_error("#{src} does not exist") unless File.exist?(src)
|
24
|
+
resources = process_overlays
|
25
|
+
|
26
|
+
if output?
|
27
|
+
puts resources_output(resources)
|
28
|
+
exit
|
29
|
+
end
|
30
|
+
|
31
|
+
if resources.empty?
|
32
|
+
warn 'nothing to do!'
|
33
|
+
exit
|
34
|
+
end
|
35
|
+
|
36
|
+
K8s::Stack.new(
|
37
|
+
name, resources,
|
38
|
+
debug: debug?,
|
39
|
+
label: LABEL,
|
40
|
+
checksum_annotation: CHECKSUM_ANNOTATION
|
41
|
+
).apply(client, prune: prune?)
|
42
|
+
|
43
|
+
puts "shot '#{pastel.cyan(name)}' successfully!" if $stdout.tty?
|
44
|
+
end
|
45
|
+
|
46
|
+
def process_overlays
|
47
|
+
resources = load_resources(src)
|
48
|
+
|
49
|
+
overlay_list.each do |overlay|
|
50
|
+
overlay_resources = from_files(overlay)
|
51
|
+
overlay_resources.each do |overlay_resource|
|
52
|
+
match = false
|
53
|
+
resources = resources.map { |r|
|
54
|
+
if same_resource?(r, overlay_resource)
|
55
|
+
match = true
|
56
|
+
r.merge(overlay_resource.to_hash)
|
57
|
+
else
|
58
|
+
r
|
59
|
+
end
|
60
|
+
}
|
61
|
+
resources << overlay_resource unless match
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
resources
|
66
|
+
end
|
67
|
+
|
68
|
+
# @param resources [Array<K8s::Resource>]
|
69
|
+
# @return [String]
|
70
|
+
def resources_output(resources)
|
71
|
+
yaml = ''
|
72
|
+
resources.each do |resource|
|
73
|
+
yaml << ::YAML.dump(stringify_hash(resource.to_hash))
|
74
|
+
end
|
75
|
+
return yaml unless $stdout.tty?
|
76
|
+
|
77
|
+
lexer = Rouge::Lexers::YAML.new
|
78
|
+
rouge = Rouge::Formatters::Terminal256.new(Rouge::Themes::Github.new)
|
79
|
+
rouge.format(lexer.lex(yaml))
|
80
|
+
end
|
81
|
+
|
82
|
+
# @return [RecursiveOpenStruct]
|
83
|
+
def variables_struct
|
84
|
+
return @variables_struct if @variables_struct
|
85
|
+
|
86
|
+
set_hash = {}
|
87
|
+
var_list.each do |var|
|
88
|
+
k, v = var.split("=", 2)
|
89
|
+
set_hash[k] = v
|
90
|
+
end
|
91
|
+
RecursiveOpenStruct.new(dotted_path_to_hash(set_hash))
|
92
|
+
end
|
93
|
+
|
94
|
+
def dotted_path_to_hash(hash)
|
95
|
+
hash.map do |pkey, pvalue|
|
96
|
+
pkey.to_s.split(".").reverse.inject(pvalue) do |value, key|
|
97
|
+
{key.to_sym => value}
|
98
|
+
end
|
99
|
+
end.inject(&:deep_merge)
|
100
|
+
end
|
101
|
+
|
102
|
+
# Stringifies all hash keys
|
103
|
+
# @return [Hash]
|
104
|
+
def stringify_hash(hash)
|
105
|
+
JSON.load(JSON.dump(hash))
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Mortar
|
2
|
+
module ClientHelper
|
3
|
+
# @return [K8s::Client]
|
4
|
+
def client
|
5
|
+
return @client if @client
|
6
|
+
|
7
|
+
if ENV['KUBE_TOKEN'] && ENV['KUBE_CA'] && ENV['KUBE_SERVER']
|
8
|
+
@client = K8s::Client.new(K8s::Transport.config(build_kubeconfig_from_env))
|
9
|
+
elsif ENV['KUBECONFIG']
|
10
|
+
@client = K8s::Client.config(K8s::Config.load_file(ENV['KUBECONFIG']))
|
11
|
+
elsif File.exist?(File.join(Dir.home, '.kube', 'config'))
|
12
|
+
@client = K8s::Client.config(K8s::Config.load_file(File.join(Dir.home, '.kube', 'config')))
|
13
|
+
else
|
14
|
+
@client = K8s::Client.in_cluster_config
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# @return [K8s::Config]
|
19
|
+
def build_kubeconfig_from_env
|
20
|
+
token = ENV['KUBE_TOKEN']
|
21
|
+
token = Base64.strict_decode64(token)
|
22
|
+
|
23
|
+
K8s::Config.new(
|
24
|
+
clusters: [
|
25
|
+
{
|
26
|
+
name: 'kubernetes',
|
27
|
+
cluster: {
|
28
|
+
server: ENV['KUBE_SERVER'],
|
29
|
+
certificate_authority_data: ENV['KUBE_CA']
|
30
|
+
}
|
31
|
+
}
|
32
|
+
],
|
33
|
+
users: [
|
34
|
+
{
|
35
|
+
name: 'mortar',
|
36
|
+
user: {
|
37
|
+
token: token
|
38
|
+
}
|
39
|
+
}
|
40
|
+
],
|
41
|
+
contexts: [
|
42
|
+
{
|
43
|
+
name: 'mortar',
|
44
|
+
context: {
|
45
|
+
cluster: 'kubernetes',
|
46
|
+
user: 'mortar'
|
47
|
+
}
|
48
|
+
}
|
49
|
+
],
|
50
|
+
preferences: {},
|
51
|
+
current_context: 'mortar'
|
52
|
+
)
|
53
|
+
rescue ArgumentError
|
54
|
+
signal_usage_error "KUBE_TOKEN env doesn't seem to be base64 encoded!"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
File without changes
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require "clamp"
|
2
|
+
require_relative "fire_command"
|
3
|
+
require_relative "yank_command"
|
4
|
+
|
5
|
+
Clamp.allow_options_after_parameters = true
|
6
|
+
|
7
|
+
module Mortar
|
8
|
+
class RootCommand < Clamp::Command
|
9
|
+
|
10
|
+
banner "mortar - Kubernetes manifest shooter"
|
11
|
+
|
12
|
+
option ['-v', '--version'], :flag, "print mortar version" do
|
13
|
+
puts "mortar #{Mortar::VERSION}"
|
14
|
+
exit 0
|
15
|
+
end
|
16
|
+
|
17
|
+
subcommand "fire", "Fire a shot (of k8s manifests)", FireCommand
|
18
|
+
subcommand "yank", "Yank a shot (of k8s manifests)", YankCommand
|
19
|
+
end
|
20
|
+
end
|
data/lib/mortar/version.rb
CHANGED
@@ -0,0 +1,40 @@
|
|
1
|
+
require_relative "command"
|
2
|
+
require_relative "mixins/client_helper"
|
3
|
+
require_relative "mixins/tty_helper"
|
4
|
+
|
5
|
+
module Mortar
|
6
|
+
class YankCommand < Mortar::Command
|
7
|
+
include Mortar::ClientHelper
|
8
|
+
include Mortar::TTYHelper
|
9
|
+
|
10
|
+
parameter "NAME", "deployment name"
|
11
|
+
|
12
|
+
option ["--force"], :flag, "use force"
|
13
|
+
|
14
|
+
def execute
|
15
|
+
unless force?
|
16
|
+
if $stdin.tty?
|
17
|
+
print "enter '#{pastel.cyan(name)}' to confirm yank: "
|
18
|
+
begin
|
19
|
+
signal_error("confirmation did not match #{pastel.cyan(name)}.") unless $stdin.gets.chomp == name
|
20
|
+
rescue Interrupt
|
21
|
+
puts
|
22
|
+
puts "Canceled"
|
23
|
+
return
|
24
|
+
end
|
25
|
+
else
|
26
|
+
signal_usage_error '--force required when running in a non-interactive mode'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
K8s::Stack.new(
|
31
|
+
name, [],
|
32
|
+
debug: debug?,
|
33
|
+
label: LABEL,
|
34
|
+
checksum_annotation: CHECKSUM_ANNOTATION
|
35
|
+
).prune(client, keep_resources: false)
|
36
|
+
|
37
|
+
puts "yanked #{pastel.cyan(name)} successfully!" if $stdout.tty?
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/lib/mortar.rb
CHANGED
@@ -1,13 +1,16 @@
|
|
1
1
|
require "clamp"
|
2
2
|
require "deep_merge"
|
3
3
|
require "mortar/version"
|
4
|
-
require "mortar/
|
4
|
+
require "mortar/root_command"
|
5
5
|
|
6
6
|
autoload :K8s, "k8s-client"
|
7
7
|
autoload :YAML, "yaml"
|
8
8
|
autoload :ERB, "erb"
|
9
9
|
autoload :Rouge, "rouge"
|
10
10
|
autoload :RecursiveOpenStruct, "recursive-open-struct"
|
11
|
+
autoload :Pastel, "pastel"
|
12
|
+
|
13
|
+
require "extensions/recursive_open_struct/each"
|
11
14
|
|
12
15
|
module Mortar
|
13
16
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kontena-mortar
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0.pre1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kontena, Inc
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-09-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: clamp
|
@@ -30,14 +30,14 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: 0.4.1
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
40
|
+
version: 0.4.1
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rouge
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -66,6 +66,20 @@ dependencies:
|
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '1.2'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: pastel
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 0.7.2
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 0.7.2
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: bundler
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -119,6 +133,7 @@ files:
|
|
119
133
|
- ".drone.yml"
|
120
134
|
- ".gitignore"
|
121
135
|
- ".rspec"
|
136
|
+
- ".travis.yml"
|
122
137
|
- Dockerfile
|
123
138
|
- Gemfile
|
124
139
|
- Gemfile.lock
|
@@ -126,12 +141,33 @@ files:
|
|
126
141
|
- README.md
|
127
142
|
- Rakefile
|
128
143
|
- bin/mortar
|
144
|
+
- build/drone/create_release.sh
|
145
|
+
- build/drone/ubuntu_xenial.sh
|
146
|
+
- build/travis/macos.sh
|
147
|
+
- examples/basic/deployment.yml
|
148
|
+
- examples/basic/service.yml
|
149
|
+
- examples/force-deployment/deployment.yml.erb
|
150
|
+
- examples/overlays/echo-metal.yml
|
151
|
+
- examples/overlays/foo/pod.yml.erb
|
152
|
+
- examples/overlays/partial/echo.yml
|
153
|
+
- examples/overlays/prod/pod.yml
|
154
|
+
- examples/overlays/prod/svc.yml
|
155
|
+
- examples/templates/env_vars/pod.yml.erb
|
156
|
+
- examples/templates/variables/loops.yml.erb
|
157
|
+
- examples/templates/variables/pod-vars.yml.erb
|
129
158
|
- kontena-mortar.gemspec
|
159
|
+
- kontena-mortar.png
|
160
|
+
- lib/extensions/recursive_open_struct/each.rb
|
130
161
|
- lib/mortar.rb
|
131
162
|
- lib/mortar/command.rb
|
132
|
-
- lib/mortar/
|
163
|
+
- lib/mortar/fire_command.rb
|
164
|
+
- lib/mortar/mixins/client_helper.rb
|
165
|
+
- lib/mortar/mixins/resource_helper.rb
|
166
|
+
- lib/mortar/mixins/tty_helper.rb
|
167
|
+
- lib/mortar/root_command.rb
|
133
168
|
- lib/mortar/version.rb
|
134
169
|
- lib/mortar/yaml_file.rb
|
170
|
+
- lib/mortar/yank_command.rb
|
135
171
|
homepage: https://github.com/kontena/mortar
|
136
172
|
licenses:
|
137
173
|
- Apache-2.0
|
@@ -147,9 +183,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
147
183
|
version: '0'
|
148
184
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
149
185
|
requirements:
|
150
|
-
- - "
|
186
|
+
- - ">"
|
151
187
|
- !ruby/object:Gem::Version
|
152
|
-
version:
|
188
|
+
version: 1.3.1
|
153
189
|
requirements: []
|
154
190
|
rubyforge_project:
|
155
191
|
rubygems_version: 2.7.6
|