mirror of https://github.com/helm/helm
parent
4d7c681ba0
commit
d58cfc46fd
@ -1,19 +0,0 @@
|
||||
*~
|
||||
.*.swp
|
||||
*.pyc
|
||||
.project
|
||||
nohup.out
|
||||
/.coverage
|
||||
/bin
|
||||
/vendor/*
|
||||
/rootfs/manager/bin/manager
|
||||
/rootfs/manager/bin/kubectl
|
||||
/rootfs/manager/bin/v1.*
|
||||
/rootfs/resourcifier/bin/resourcifier
|
||||
/rootfs/resourcifier/bin/kubectl
|
||||
/rootfs/resourcifier/bin/v1.*
|
||||
/rootfs/expandybird/bin/expandybird
|
||||
/rootfs/expandybird/opt/expansion
|
||||
.DS_Store
|
||||
/log/
|
||||
/scripts/env.sh
|
@ -1,202 +0,0 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
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.
|
@ -1,61 +0,0 @@
|
||||
# Helm Maintainers
|
||||
|
||||
This document explains the leadership structure of the Kubernetes Helm project, and list the current project maintainers.
|
||||
|
||||
## What is a Maintainer?
|
||||
|
||||
(Unabashedly stolen from the [Docker](https://github.com/docker/docker/blob/master/MAINTAINERS) project)
|
||||
|
||||
There are different types of maintainers, with different responsibilities, but
|
||||
all maintainers have 3 things in common:
|
||||
|
||||
1. They share responsibility in the project's success.
|
||||
2. They have made a long-term, recurring time investment to improve the project.
|
||||
3. They spend that time doing whatever needs to be done, not necessarily what
|
||||
is the most interesting or fun.
|
||||
|
||||
## Types of Maintainers
|
||||
|
||||
The Helm project includes two types of official maintainers: maintainers and core maintainers.
|
||||
|
||||
### Helm Maintainers
|
||||
|
||||
Helm maintainers are developers who have commit access to the Helm repository.
|
||||
The duties of a maintainer include:
|
||||
|
||||
* Classify and respond to GitHub issues and review pull requests
|
||||
* Perform code reviews
|
||||
* Shape the Helm roadmap and lead efforts to accomplish roadmap milestones
|
||||
* Participate actively in feature development and bug fixing
|
||||
* Answer questions and help users
|
||||
* Participate in planning meetings
|
||||
|
||||
### Helm Core Maintainers
|
||||
|
||||
In addition to the duties of a Maintainer, Helm Core Maintainers also:
|
||||
|
||||
* Coordinate planning meetings
|
||||
* Triage GitHub issues for milestone planning
|
||||
* Escalate emergency issues (broken builds, security flaws) outside of
|
||||
the normal planning process
|
||||
|
||||
The current core maintainers of Helm:
|
||||
|
||||
* Jack Greenfield - [@jackgr](https://github.com/jackgr)
|
||||
* Matt Butcher - [@technosophos](https://github.com/technosophos)
|
||||
|
||||
## Project Planning
|
||||
|
||||
The Helm team holds regular planning meetings to set the project direction, milestones, and relative prioritization of issues. Planning meetings are coordinated via the #Helm room in the [Kubernetes Slack](http://slack.kubernetes.io/).
|
||||
|
||||
In order to solicit feedback from the community, planning meetings are run in public whenever possible.
|
||||
|
||||
## Becoming a Maintainer
|
||||
|
||||
Generally, potential maintainers are selected by the existing core maintainers based in part on the following criteria:
|
||||
|
||||
* Sustained contributions to the project over a period of time (usually months)
|
||||
* A willingness to help users on GitHub and in the [#Helm Slack room](http://slack.kubernetes.io/)
|
||||
* A friendly attitude
|
||||
|
||||
The Helm core maintainers must unanimously agree before inviting a community member to join as a maintainer, although in many cases the candidate has already been acting in the capacity of a maintainer for some time, and has been consulted on issues, pull requests, etc.
|
@ -1,118 +0,0 @@
|
||||
# Copyright 2015 The Kubernetes Authors All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# 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.
|
||||
|
||||
GO_DIRS ?= $(shell glide nv -x )
|
||||
GO_PKGS ?= $(shell glide nv)
|
||||
|
||||
ROOTFS := rootfs
|
||||
CLIENT := cmd/helm
|
||||
|
||||
.PHONY: info
|
||||
info:
|
||||
$(MAKE) -C $(ROOTFS) $@
|
||||
|
||||
.PHONY: gocheck
|
||||
ifndef GOPATH
|
||||
$(error No GOPATH set)
|
||||
endif
|
||||
|
||||
.PHONY: build
|
||||
build: gocheck
|
||||
@scripts/build-go.sh
|
||||
|
||||
.PHONY: build-static
|
||||
build-static: gocheck
|
||||
@BUILD_TYPE=STATIC scripts/build-go.sh
|
||||
|
||||
.PHONY: build-cross
|
||||
build-cross: gocheck
|
||||
@BUILD_TYPE=CROSS scripts/build-go.sh
|
||||
|
||||
.PHONY: all
|
||||
all: build
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
$(MAKE) -C $(ROOTFS) $@
|
||||
go clean -v $(GO_PKGS)
|
||||
rm -rf bin
|
||||
|
||||
.PHONY: test
|
||||
test: build test-style test-unit test-flake8
|
||||
|
||||
.PHONY: quicktest
|
||||
quicktest: test-style
|
||||
go test $(GO_PKGS)
|
||||
|
||||
.PHONY: push
|
||||
push: push-server push-client
|
||||
|
||||
.PHONY: push-server
|
||||
push-server: build-static
|
||||
$(MAKE) -C $(ROOTFS) push
|
||||
|
||||
.PHONY: push-client
|
||||
push-client: gocheck
|
||||
@BUILD_TYPE=CROSS scripts/build-go.sh $(CLIENT)
|
||||
$(MAKE) -C $(CLIENT) push
|
||||
|
||||
.PHONY: container
|
||||
container: build-static
|
||||
$(MAKE) -C $(ROOTFS) $@
|
||||
|
||||
.PHONY: test-unit
|
||||
test-unit:
|
||||
@echo Running tests...
|
||||
go test -race -v $(GO_PKGS)
|
||||
|
||||
.PHONY: test-flake8
|
||||
test-flake8:
|
||||
@echo Running flake8...
|
||||
flake8 expansion
|
||||
@echo ----------------
|
||||
|
||||
.PHONY: test-style
|
||||
test-style:
|
||||
@scripts/validate-go.sh
|
||||
|
||||
HAS_GLIDE := $(shell command -v glide;)
|
||||
HAS_GOLINT := $(shell command -v golint;)
|
||||
HAS_GOVET := $(shell command -v go tool vet;)
|
||||
HAS_GOX := $(shell command -v gox;)
|
||||
HAS_PIP := $(shell command -v pip;)
|
||||
HAS_FLAKE8 := $(shell command -v flake8;)
|
||||
|
||||
.PHONY: bootstrap
|
||||
bootstrap:
|
||||
@echo Installing deps
|
||||
ifndef HAS_PIP
|
||||
$(error Please install the latest version of Python pip)
|
||||
endif
|
||||
ifndef HAS_GLIDE
|
||||
go get -u github.com/Masterminds/glide
|
||||
endif
|
||||
ifndef HAS_GOLINT
|
||||
go get -u github.com/golang/lint/golint
|
||||
endif
|
||||
ifndef HAS_GOVET
|
||||
go get -u golang.org/x/tools/cmd/vet
|
||||
endif
|
||||
ifndef HAS_GOX
|
||||
go get -u github.com/mitchellh/gox
|
||||
endif
|
||||
ifndef HAS_FLAKE8
|
||||
pip install flake8
|
||||
endif
|
||||
glide install
|
||||
pip install --user -r expansion/requirements.txt
|
@ -1,162 +0,0 @@
|
||||
# Helm
|
||||
|
||||
[](https://circleci.com/gh/kubernetes/helm) [](http://goreportcard.com/report/kubernetes/helm)
|
||||
|
||||
Helm makes it easy to create, describe, update and
|
||||
delete Kubernetes resources using declarative configuration. A configuration is
|
||||
just a `YAML` file that configures Kubernetes resources or supplies parameters
|
||||
to templates.
|
||||
|
||||
Helm Manager runs server side, in your Kubernetes cluster, so it can tell you what templates
|
||||
you've instantiated there, what resources they created, and even how the resources
|
||||
are organized. So, for example, you can ask questions like:
|
||||
|
||||
* What Redis instances are running in this cluster?
|
||||
* What Redis master and slave services are part of this Redis instance?
|
||||
* What pods are part of this Redis slave?
|
||||
|
||||
The official Helm repository of charts is available in the
|
||||
[kubernetes/charts](https://github.com/kubernetes/charts) repository.
|
||||
|
||||
Please hang out with us in [the Slack chat room](https://kubernetes.slack.com/messages/helm/).
|
||||
|
||||
## Installing Helm
|
||||
|
||||
Note: if you're exploring or using the project, you'll probably want to pull
|
||||
[the latest release](https://github.com/kubernetes/helm/releases/latest),
|
||||
since there may be undiscovered or unresolved issues at HEAD.
|
||||
|
||||
From a Linux or Mac OS X client:
|
||||
|
||||
```
|
||||
$ git clone https://github.com/kubernetes/helm.git
|
||||
$ cd helm
|
||||
$ make build
|
||||
$ bin/helm server install
|
||||
```
|
||||
|
||||
That's it. You can now use `kubectl` to see Helm running in your cluster like this:
|
||||
|
||||
```
|
||||
$ kubectl get pod,rc,service --namespace=helm
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
expandybird-rc-e0whp 1/1 Running 0 35m
|
||||
expandybird-rc-zdp8w 1/1 Running 0 35m
|
||||
manager-rc-bl4i4 1/1 Running 0 35m
|
||||
resourcifier-rc-21clg 1/1 Running 0 35m
|
||||
resourcifier-rc-i2zhi 1/1 Running 0 35m
|
||||
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
||||
expandybird-service 10.0.0.248 <none> 8081/TCP 35m
|
||||
manager-service 10.0.0.49 <none> 8080/TCP 35m
|
||||
resourcifier-service 10.0.0.184 <none> 8082/TCP 35m
|
||||
NAME DESIRED CURRENT AGE
|
||||
expandybird-rc 2 2 35m
|
||||
manager-rc 1 1 35m
|
||||
resourcifier-rc 2 2 35m
|
||||
```
|
||||
|
||||
If you see expandybird, manager and resourcifier services, as well as expandybird, manager and resourcifier replication controllers with pods that are READY, then Helm is up and running!
|
||||
|
||||
## Using Helm
|
||||
|
||||
Run a Kubernetes proxy to allow the Helm client to connect to the remote cluster:
|
||||
|
||||
```
|
||||
kubectl proxy --port=8001 &
|
||||
```
|
||||
|
||||
Configure the HELM_HOST environment variable to let the local Helm client talk to the Helm manager service running in your remote Kubernetes cluster using the proxy.
|
||||
|
||||
```
|
||||
export HELM_HOST=http://localhost:8001/api/v1/proxy/namespaces/helm/services/manager-service:manager
|
||||
```
|
||||
|
||||
## Installing Charts
|
||||
|
||||
To quickly deploy a chart, you can use the Helm command line tool.
|
||||
|
||||
Currently here is the step by step guide.
|
||||
|
||||
First add a respository of Charts used for testing:
|
||||
|
||||
```
|
||||
$ bin/helm repo add kubernetes-charts-testing gs://kubernetes-charts-testing
|
||||
```
|
||||
|
||||
Then deploy a Chart from this repository. For example to start a Redis cluster:
|
||||
|
||||
```
|
||||
$ bin/helm deploy --name test --properties "workers=2" gs://kubernetes-charts-testing/redis-2.0.0.tgz
|
||||
```
|
||||
The command above will create a helm "deployment" called `test` using the `redis-2.0.0.tgz` chart stored in the google storage bucket `kubernetes-charts-testing`.
|
||||
|
||||
`$ bin/helm deployment describe test` will allow you to see the status of the resources you just created using the redis-2.0.0.tgz chart. You can also use kubectl to see the the same resources. It'll look like this:
|
||||
|
||||
```
|
||||
$ kubectl get pods,svc,rc
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
barfoo-barfoo 5/5 Running 0 45m
|
||||
redis-master-rc-8wrqt 1/1 Running 0 41m
|
||||
redis-slave-rc-6ptx6 1/1 Running 0 41m
|
||||
redis-slave-rc-yc12q 1/1 Running 0 41m
|
||||
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
||||
kubernetes 10.0.0.1 <none> 443/TCP 45m
|
||||
redis-master 10.0.0.67 <none> 6379/TCP 41m
|
||||
redis-slave 10.0.0.168 <none> 6379/TCP 41m
|
||||
NAME DESIRED CURRENT AGE
|
||||
redis-master-rc 1 1 41m
|
||||
redis-slave-rc 2 2 41m
|
||||
```
|
||||
|
||||
To connect to your Redis master with a local `redis-cli` just use `kubectl port-forward` in a similar manner to:
|
||||
|
||||
```
|
||||
$ kubectl port-forward redis-master-rc-8wrqt 6379:639 &
|
||||
$ redis-cli
|
||||
127.0.0.1:6379> info
|
||||
...
|
||||
role:master
|
||||
connected_slaves:2
|
||||
slave0:ip=172.17.0.10,port=6379,state=online,offset=925,lag=0
|
||||
slave1:ip=172.17.0.11,port=6379,state=online,offset=925,lag=1
|
||||
```
|
||||
|
||||
Once you are done, you can delete your deployment with
|
||||
|
||||
```
|
||||
$ bin/helm deployment list
|
||||
test
|
||||
$ bin/helm deployment rm test
|
||||
````
|
||||
|
||||
## Uninstalling Helm from Kubernetes
|
||||
|
||||
You can uninstall Helm entirely using the following command:
|
||||
|
||||
```
|
||||
$ bin/helm server uninstall
|
||||
```
|
||||
|
||||
This command will remove everything in the Helm namespace being used.
|
||||
|
||||
## Design of Helm
|
||||
|
||||
There is a more detailed [design document](docs/design/design.md) available.
|
||||
|
||||
## Status of the Project
|
||||
|
||||
This project is still under active development, so you might run into issues. If
|
||||
you do, please don't be shy about letting us know, or better yet, contribute a
|
||||
fix or feature.
|
||||
|
||||
## Contributing
|
||||
Your contributions are welcome.
|
||||
|
||||
We use the same [workflow](https://github.com/kubernetes/kubernetes/blob/master/docs/devel/development.md#git-setup),
|
||||
[License](LICENSE) and [Contributor License Agreement](CONTRIBUTING.md) as the main Kubernetes repository.
|
||||
|
||||
## Relationship to Google Cloud Platform's Deployment Manager and Deis's Helm
|
||||
Kubernetes Helm represent a merge of Google's Deployment Manager (DM) and the original Helm from Deis.
|
||||
Kubernetes Helm uses many of the same concepts and languages as
|
||||
[Google Cloud Deployment Manager](https://cloud.google.com/deployment-manager/overview),
|
||||
but creates resources in Kubernetes clusters, not in Google Cloud Platform projects. It also brings several concepts from the original Helm such as Charts.
|
@ -1,33 +0,0 @@
|
||||
machine:
|
||||
environment:
|
||||
GLIDE_VERSION: "0.10.1"
|
||||
GO15VENDOREXPERIMENT: 1
|
||||
GOPATH: /usr/local/go_workspace
|
||||
HOME: /home/ubuntu
|
||||
IMPORT_PATH: "github.com/kubernetes/helm"
|
||||
PATH: $HOME/go/bin:$PATH
|
||||
GOROOT: $HOME/go
|
||||
|
||||
dependencies:
|
||||
override:
|
||||
- mkdir -p $HOME/go
|
||||
- wget "https://storage.googleapis.com/golang/go1.6.linux-amd64.tar.gz"
|
||||
- tar -C $HOME -xzf go1.6.linux-amd64.tar.gz
|
||||
- go version
|
||||
- go env
|
||||
- sudo chown -R $(whoami):staff /usr/local
|
||||
- cd $GOPATH
|
||||
- mkdir -p $GOPATH/src/$IMPORT_PATH
|
||||
- cd $HOME/helm
|
||||
- rsync -az --delete ./ "$GOPATH/src/$IMPORT_PATH/"
|
||||
- wget "https://github.com/Masterminds/glide/releases/download/$GLIDE_VERSION/glide-$GLIDE_VERSION-linux-amd64.tar.gz"
|
||||
- mkdir -p $HOME/bin
|
||||
- tar -vxz -C $HOME/bin --strip=1 -f glide-$GLIDE_VERSION-linux-amd64.tar.gz
|
||||
- export PATH="$HOME/bin:$PATH" GLIDE_HOME="$HOME/.glide"
|
||||
- cd $GOPATH/src/$IMPORT_PATH
|
||||
- sudo pip install -r expansion/requirements.txt
|
||||
- sudo pip install flake8
|
||||
|
||||
test:
|
||||
override:
|
||||
- cd $GOPATH/src/$IMPORT_PATH && make bootstrap test
|
@ -1,18 +0,0 @@
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
// Package cmd contains the executables for Helm.
|
||||
package cmd
|
@ -1,131 +0,0 @@
|
||||
/*
|
||||
Copyright 2015 The Kubernetes Authors All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
package expander
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/ghodss/yaml"
|
||||
"log"
|
||||
"os/exec"
|
||||
|
||||
"github.com/kubernetes/helm/pkg/expansion"
|
||||
)
|
||||
|
||||
type expander struct {
|
||||
ExpansionBinary string
|
||||
}
|
||||
|
||||
// NewExpander returns an ExpandyBird expander.
|
||||
func NewExpander(binary string) expansion.Expander {
|
||||
return &expander{binary}
|
||||
}
|
||||
|
||||
type expandyBirdConfigOutput struct {
|
||||
Resources []interface{} `yaml:"resources,omitempty"`
|
||||
}
|
||||
|
||||
type expandyBirdOutput struct {
|
||||
Config *expandyBirdConfigOutput `yaml:"config,omitempty"`
|
||||
Layout interface{} `yaml:"layout,omitempty"`
|
||||
}
|
||||
|
||||
// ExpandChart passes the given configuration to the expander and returns the
|
||||
// expanded configuration as a string on success.
|
||||
func (e *expander) ExpandChart(request *expansion.ServiceRequest) (*expansion.ServiceResponse, error) {
|
||||
|
||||
if err := expansion.ValidateRequest(request); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
request, err := expansion.ValidateProperties(request)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
chartInv := request.ChartInvocation
|
||||
chartFile := request.Chart.Chartfile
|
||||
chartMembers := request.Chart.Members
|
||||
|
||||
if e.ExpansionBinary == "" {
|
||||
message := fmt.Sprintf("expansion binary cannot be empty")
|
||||
return nil, fmt.Errorf("%s: %s", chartInv.Name, message)
|
||||
}
|
||||
|
||||
entrypointIndex := -1
|
||||
for i, f := range chartMembers {
|
||||
if f.Path == chartFile.Expander.Entrypoint {
|
||||
entrypointIndex = i
|
||||
}
|
||||
}
|
||||
if entrypointIndex == -1 {
|
||||
message := fmt.Sprintf("The entrypoint in the chart.yaml cannot be found: %s", chartFile.Expander.Entrypoint)
|
||||
return nil, fmt.Errorf("%s: %s", chartInv.Name, message)
|
||||
}
|
||||
|
||||
// Those are automatically increasing buffers, so writing arbitrary large
|
||||
// data here won't block the child process.
|
||||
var stdout bytes.Buffer
|
||||
var stderr bytes.Buffer
|
||||
|
||||
// Now we convert the new chart representation into the form that classic ExpandyBird takes.
|
||||
|
||||
chartInvJSON, err := json.Marshal(chartInv)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error marshalling chart invocation %s: %s", chartInv.Name, err)
|
||||
}
|
||||
content := "{ \"resources\": [" + string(chartInvJSON) + "] }"
|
||||
|
||||
cmd := &exec.Cmd{
|
||||
Path: e.ExpansionBinary,
|
||||
// Note, that binary name still has to be passed argv[0].
|
||||
Args: []string{e.ExpansionBinary, content},
|
||||
Stdout: &stdout,
|
||||
Stderr: &stderr,
|
||||
}
|
||||
|
||||
for i, f := range chartMembers {
|
||||
name := f.Path
|
||||
path := f.Path
|
||||
if i == entrypointIndex {
|
||||
// This is how expandyBird identifies the entrypoint.
|
||||
name = chartInv.Type
|
||||
}
|
||||
cmd.Args = append(cmd.Args, name, path, string(f.Content))
|
||||
}
|
||||
|
||||
if err := cmd.Start(); err != nil {
|
||||
log.Printf("error starting expansion process: %s", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cmd.Wait()
|
||||
|
||||
log.Printf("Expansion process: pid: %d SysTime: %v UserTime: %v", cmd.ProcessState.Pid(),
|
||||
cmd.ProcessState.SystemTime(), cmd.ProcessState.UserTime())
|
||||
if stderr.String() != "" {
|
||||
return nil, fmt.Errorf("%s: %s", chartInv.Name, stderr.String())
|
||||
}
|
||||
|
||||
output := &expandyBirdOutput{}
|
||||
if err := yaml.Unmarshal(stdout.Bytes(), output); err != nil {
|
||||
return nil, fmt.Errorf("cannot unmarshal expansion result (%s):\n%s", err, output)
|
||||
}
|
||||
|
||||
return &expansion.ServiceResponse{Resources: output.Config.Resources}, nil
|
||||
}
|
@ -1,832 +0,0 @@
|
||||
/*
|
||||
Copyright 2015 The Kubernetes Authors All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
package expander
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/kubernetes/helm/pkg/chart"
|
||||
"github.com/kubernetes/helm/pkg/common"
|
||||
"github.com/kubernetes/helm/pkg/expansion"
|
||||
)
|
||||
|
||||
var expanderName = "../../../expansion/expansion.py"
|
||||
|
||||
// content provides an easy way to provide file content verbatim in tests.
|
||||
func content(lines []string) []byte {
|
||||
return []byte(strings.Join(lines, "\n") + "\n")
|
||||
}
|
||||
|
||||
func getChartNameFromPC(pc uintptr) string {
|
||||
rf := runtime.FuncForPC(pc)
|
||||
fn := rf.Name()
|
||||
bn := filepath.Base(fn)
|
||||
split := strings.Split(bn, ".")
|
||||
if len(split) > 1 {
|
||||
split = split[1:]
|
||||
}
|
||||
|
||||
cn := fmt.Sprintf("%s-1.2.3.tgz", split[0])
|
||||
return cn
|
||||
}
|
||||
|
||||
func getChartURLFromPC(pc uintptr) string {
|
||||
cn := getChartNameFromPC(pc)
|
||||
cu := fmt.Sprintf("gs://kubernetes-charts-testing/%s", cn)
|
||||
return cu
|
||||
}
|
||||
|
||||
func getTestChartName(t *testing.T) string {
|
||||
pc, _, _, _ := runtime.Caller(1)
|
||||
cu := getChartURLFromPC(pc)
|
||||
cl, err := chart.Parse(cu)
|
||||
if err != nil {
|
||||
t.Fatalf("cannot parse chart reference %s: %s", cu, err)
|
||||
}
|
||||
|
||||
return cl.Name
|
||||
}
|
||||
|
||||
func getTestChartURL() string {
|
||||
pc, _, _, _ := runtime.Caller(1)
|
||||
cu := getChartURLFromPC(pc)
|
||||
return cu
|
||||
}
|
||||
|
||||
func testExpansion(t *testing.T, req *expansion.ServiceRequest,
|
||||
expResponse *expansion.ServiceResponse, expError string) {
|
||||
backend := NewExpander(expanderName)
|
||||
response, err := backend.ExpandChart(req)
|
||||
if err != nil {
|
||||
message := err.Error()
|
||||
if expResponse != nil || !strings.Contains(message, expError) {
|
||||
t.Fatalf("unexpected error: %v\n", err)
|
||||
}
|
||||
} else {
|
||||
if expResponse == nil {
|
||||
t.Fatalf("expected error did not occur: %s\n", expError)
|
||||
}
|
||||
if !reflect.DeepEqual(response, expResponse) {
|
||||
message := fmt.Sprintf(
|
||||
"want:\n%s\nhave:\n%s\n", expResponse, response)
|
||||
t.Fatalf("output mismatch:\n%s\n", message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var pyExpander = &chart.Expander{
|
||||
Name: "ExpandyBird",
|
||||
Entrypoint: "templates/main.py",
|
||||
}
|
||||
|
||||
var jinjaExpander = &chart.Expander{
|
||||
Name: "ExpandyBird",
|
||||
Entrypoint: "templates/main.jinja",
|
||||
}
|
||||
|
||||
func TestEmptyJinja(t *testing.T) {
|
||||
testExpansion(
|
||||
t,
|
||||
&expansion.ServiceRequest{
|
||||
ChartInvocation: &common.Resource{
|
||||
Name: "test_invocation",
|
||||
Type: getTestChartURL(),
|
||||
},
|
||||
Chart: &chart.Content{
|
||||
Chartfile: &chart.Chartfile{
|
||||
Name: getTestChartName(t),
|
||||
Expander: jinjaExpander,
|
||||
},
|
||||
Members: []*chart.Member{
|
||||
{
|
||||
Path: "templates/main.jinja",
|
||||
Content: content([]string{"resources:"}),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
&expansion.ServiceResponse{
|
||||
Resources: []interface{}{},
|
||||
},
|
||||
"", // Error
|
||||
)
|
||||
}
|
||||
|
||||
func TestEmptyPython(t *testing.T) {
|
||||
testExpansion(
|
||||
t,
|
||||
&expansion.ServiceRequest{
|
||||
ChartInvocation: &common.Resource{
|
||||
Name: "test_invocation",
|
||||
Type: getTestChartURL(),
|
||||
},
|
||||
Chart: &chart.Content{
|
||||
Chartfile: &chart.Chartfile{
|
||||
Name: getTestChartName(t),
|
||||
Expander: pyExpander,
|
||||
},
|
||||
Members: []*chart.Member{
|
||||
{
|
||||
Path: "templates/main.py",
|
||||
Content: content([]string{
|
||||
"def GenerateConfig(ctx):",
|
||||
" return 'resources:'",
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
&expansion.ServiceResponse{
|
||||
Resources: []interface{}{},
|
||||
},
|
||||
"", // Error
|
||||
)
|
||||
}
|
||||
|
||||
func TestSimpleJinja(t *testing.T) {
|
||||
testExpansion(
|
||||
t,
|
||||
&expansion.ServiceRequest{
|
||||
ChartInvocation: &common.Resource{
|
||||
Name: "test_invocation",
|
||||
Type: getTestChartURL(),
|
||||
},
|
||||
Chart: &chart.Content{
|
||||
Chartfile: &chart.Chartfile{
|
||||
Name: getTestChartName(t),
|
||||
Expander: jinjaExpander,
|
||||
},
|
||||
Members: []*chart.Member{
|
||||
{
|
||||
Path: "templates/main.jinja",
|
||||
Content: content([]string{
|
||||
"resources:",
|
||||
"- name: foo",
|
||||
" type: bar",
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
&expansion.ServiceResponse{
|
||||
Resources: []interface{}{
|
||||
map[string]interface{}{
|
||||
"name": "foo",
|
||||
"type": "bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
"", // Error
|
||||
)
|
||||
}
|
||||
|
||||
func TestSimplePython(t *testing.T) {
|
||||
testExpansion(
|
||||
t,
|
||||
&expansion.ServiceRequest{
|
||||
ChartInvocation: &common.Resource{
|
||||
Name: "test_invocation",
|
||||
Type: getTestChartURL(),
|
||||
},
|
||||
Chart: &chart.Content{
|
||||
Chartfile: &chart.Chartfile{
|
||||
Name: getTestChartName(t),
|
||||
Expander: pyExpander,
|
||||
},
|
||||
Members: []*chart.Member{
|
||||
{
|
||||
Path: "templates/main.py",
|
||||
Content: content([]string{
|
||||
"def GenerateConfig(ctx):",
|
||||
" return '''resources:",
|
||||
"- name: foo",
|
||||
" type: bar",
|
||||
"'''",
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
&expansion.ServiceResponse{
|
||||
Resources: []interface{}{
|
||||
map[string]interface{}{
|
||||
"name": "foo",
|
||||
"type": "bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
"", // Error
|
||||
)
|
||||
}
|
||||
|
||||
func TestPropertiesJinja(t *testing.T) {
|
||||
testExpansion(
|
||||
t,
|
||||
&expansion.ServiceRequest{
|
||||
ChartInvocation: &common.Resource{
|
||||
Name: "test_invocation",
|
||||
Type: getTestChartURL(),
|
||||
Properties: map[string]interface{}{
|
||||
"prop1": 3.0,
|
||||
"prop2": "foo",
|
||||
},
|
||||
},
|
||||
Chart: &chart.Content{
|
||||
Chartfile: &chart.Chartfile{
|
||||
Name: getTestChartName(t),
|
||||
Expander: jinjaExpander,
|
||||
},
|
||||
Members: []*chart.Member{
|
||||
{
|
||||
Path: "templates/main.jinja",
|
||||
Content: content([]string{
|
||||
"resources:",
|
||||
"- name: foo",
|
||||
" type: {{ properties.prop2 }}",
|
||||
" properties:",
|
||||
" something: {{ properties.prop1 }}",
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
&expansion.ServiceResponse{
|
||||
Resources: []interface{}{
|
||||
map[string]interface{}{
|
||||
"name": "foo",
|
||||
"properties": map[string]interface{}{
|
||||
"something": 3.0,
|
||||
},
|
||||
"type": "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
"", // Error
|
||||
)
|
||||
}
|
||||
|
||||
func TestPropertiesPython(t *testing.T) {
|
||||
testExpansion(
|
||||
t,
|
||||
&expansion.ServiceRequest{
|
||||
ChartInvocation: &common.Resource{
|
||||
Name: "test_invocation",
|
||||
Type: getTestChartURL(),
|
||||
Properties: map[string]interface{}{
|
||||
"prop1": 3.0,
|
||||
"prop2": "foo",
|
||||
},
|
||||
},
|
||||
Chart: &chart.Content{
|
||||
Chartfile: &chart.Chartfile{
|
||||
Name: getTestChartName(t),
|
||||
Expander: pyExpander,
|
||||
},
|
||||
Members: []*chart.Member{
|
||||
{
|
||||
Path: "templates/main.py",
|
||||
Content: content([]string{
|
||||
"def GenerateConfig(ctx):",
|
||||
" return '''resources:",
|
||||
"- name: foo",
|
||||
" type: %(prop2)s",
|
||||
" properties:",
|
||||
" something: %(prop1)s",
|
||||
"''' % ctx.properties",
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
&expansion.ServiceResponse{
|
||||
Resources: []interface{}{
|
||||
map[string]interface{}{
|
||||
"name": "foo",
|
||||
"properties": map[string]interface{}{
|
||||
"something": 3.0,
|
||||
},
|
||||
"type": "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
"", // Error
|
||||
)
|
||||
}
|
||||
|
||||
func TestMultiFileJinja(t *testing.T) {
|
||||
testExpansion(
|
||||
t,
|
||||
&expansion.ServiceRequest{
|
||||
ChartInvocation: &common.Resource{
|
||||
Name: "test_invocation",
|
||||
Type: getTestChartURL(),
|
||||
},
|
||||
Chart: &chart.Content{
|
||||
Chartfile: &chart.Chartfile{
|
||||
Name: getTestChartName(t),
|
||||
Expander: jinjaExpander,
|
||||
},
|
||||
Members: []*chart.Member{
|
||||
{
|
||||
Path: "templates/main.jinja",
|
||||
Content: content([]string{"{% include 'templates/secondary.jinja' %}"}),
|
||||
},
|
||||
{
|
||||
Path: "templates/secondary.jinja",
|
||||
Content: content([]string{
|
||||
"resources:",
|
||||
"- name: foo",
|
||||
" type: bar",
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
&expansion.ServiceResponse{
|
||||
Resources: []interface{}{
|
||||
map[string]interface{}{
|
||||
"name": "foo",
|
||||
"type": "bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
"", // Error
|
||||
)
|
||||
}
|
||||
|
||||
var schemaContent = content([]string{
|
||||
`{`,
|
||||
` "required": ["prop1", "prop2"],`,
|
||||
` "additionalProperties": false,`,
|
||||
` "properties": {`,
|
||||
` "prop1": {`,
|
||||
` "description": "Nice description.",`,
|
||||
` "type": "integer"`,
|
||||
` },`,
|
||||
` "prop2": {`,
|
||||
` "description": "Nice description.",`,
|
||||
` "type": "string"`,
|
||||
` }`,
|
||||
` }`,
|
||||
`}`,
|
||||
})
|
||||
|
||||
func TestSchema(t *testing.T) {
|
||||
testExpansion(
|
||||
t,
|
||||
&expansion.ServiceRequest{
|
||||
ChartInvocation: &common.Resource{
|
||||
Name: "test_invocation",
|
||||
Type: getTestChartURL(),
|
||||
Properties: map[string]interface{}{
|
||||
"prop1": 3.0,
|
||||
"prop2": "foo",
|
||||
},
|
||||
},
|
||||
Chart: &chart.Content{
|
||||
Chartfile: &chart.Chartfile{
|
||||
Name: getTestChartName(t),
|
||||
Expander: jinjaExpander,
|
||||
Schema: "Schema.yaml",
|
||||
},
|
||||
Members: []*chart.Member{
|
||||
{
|
||||
Path: "Schema.yaml",
|
||||
Content: schemaContent,
|
||||
},
|
||||
{
|
||||
Path: "templates/main.jinja",
|
||||
Content: content([]string{
|
||||
"resources:",
|
||||
"- name: foo",
|
||||
" type: {{ properties.prop2 }}",
|
||||
" properties:",
|
||||
" something: {{ properties.prop1 }}",
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
&expansion.ServiceResponse{
|
||||
Resources: []interface{}{
|
||||
map[string]interface{}{
|
||||
"name": "foo",
|
||||
"properties": map[string]interface{}{
|
||||
"something": 3.0,
|
||||
},
|
||||
"type": "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
"", // Error
|
||||
)
|
||||
}
|
||||
|
||||
func TestSchemaFail(t *testing.T) {
|
||||
testExpansion(
|
||||
t,
|
||||
&expansion.ServiceRequest{
|
||||
ChartInvocation: &common.Resource{
|
||||
Name: "test_invocation",
|
||||
Type: getTestChartURL(),
|
||||
Properties: map[string]interface{}{
|
||||
"prop1": 3.0,
|
||||
"prop3": "foo",
|
||||
},
|
||||
},
|
||||
Chart: &chart.Content{
|
||||
Chartfile: &chart.Chartfile{
|
||||
Name: getTestChartName(t),
|
||||
Expander: jinjaExpander,
|
||||
Schema: "Schema.yaml",
|
||||
},
|
||||
Members: []*chart.Member{
|
||||
{
|
||||
Path: "Schema.yaml",
|
||||
Content: schemaContent,
|
||||
},
|
||||
{
|
||||
Path: "templates/main.jinja",
|
||||
Content: content([]string{
|
||||
"resources:",
|
||||
"- name: foo",
|
||||
" type: {{ properties.prop2 }}",
|
||||
" properties:",
|
||||
" something: {{ properties.prop1 }}",
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
nil, // Response.
|
||||
`"prop2" property is missing and required`,
|
||||
)
|
||||
}
|
||||
|
||||
func TestMultiFileJinjaMissing(t *testing.T) {
|
||||
testExpansion(
|
||||
t,
|
||||
&expansion.ServiceRequest{
|
||||
ChartInvocation: &common.Resource{
|
||||
Name: "test_invocation",
|
||||
Type: getTestChartURL(),
|
||||
},
|
||||
Chart: &chart.Content{
|
||||
Chartfile: &chart.Chartfile{
|
||||
Name: getTestChartName(t),
|
||||
Expander: jinjaExpander,
|
||||
},
|
||||
Members: []*chart.Member{
|
||||
{
|
||||
Path: "templates/main.jinja",
|
||||
Content: content([]string{"{% include 'templates/secondary.jinja' %}"}),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
nil, // Response
|
||||
"TemplateNotFound: templates/secondary.jinja",
|
||||
)
|
||||
}
|
||||
|
||||
func TestMultiFilePython(t *testing.T) {
|
||||
testExpansion(
|
||||
t,
|
||||
&expansion.ServiceRequest{
|
||||
ChartInvocation: &common.Resource{
|
||||
Name: "test_invocation",
|
||||
Type: getTestChartURL(),
|
||||
},
|
||||
Chart: &chart.Content{
|
||||
Chartfile: &chart.Chartfile{
|
||||
Name: getTestChartName(t),
|
||||
Expander: pyExpander,
|
||||
},
|
||||
Members: []*chart.Member{
|
||||
{
|
||||
Path: "templates/main.py",
|
||||
Content: content([]string{
|
||||
"from templates import second",
|
||||
"import templates.third",
|
||||
"def GenerateConfig(ctx):",
|
||||
" t2 = second.Gen()",
|
||||
" t3 = templates.third.Gen()",
|
||||
" return t2",
|
||||
}),
|
||||
},
|
||||
{
|
||||
Path: "templates/second.py",
|
||||
Content: content([]string{
|
||||
"def Gen():",
|
||||
" return '''resources:",
|
||||
"- name: foo",
|
||||
" type: bar",
|
||||
"'''",
|
||||
}),
|
||||
},
|
||||
{
|
||||
Path: "templates/third.py",
|
||||
Content: content([]string{
|
||||
"def Gen():",
|
||||
" return '''resources:",
|
||||
"- name: foo",
|
||||
" type: bar",
|
||||
"'''",
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
&expansion.ServiceResponse{
|
||||
Resources: []interface{}{
|
||||
map[string]interface{}{
|
||||
"name": "foo",
|
||||
"type": "bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
"", // Error
|
||||
)
|
||||
}
|
||||
|
||||
func TestMultiFilePythonMissing(t *testing.T) {
|
||||
testExpansion(
|
||||
t,
|
||||
&expansion.ServiceRequest{
|
||||
ChartInvocation: &common.Resource{
|
||||
Name: "test_invocation",
|
||||
Type: getTestChartURL(),
|
||||
},
|
||||
Chart: &chart.Content{
|
||||
Chartfile: &chart.Chartfile{
|
||||
Name: getTestChartName(t),
|
||||
Expander: pyExpander,
|
||||
},
|
||||
Members: []*chart.Member{
|
||||
{
|
||||
Path: "templates/main.py",
|
||||
Content: content([]string{
|
||||
"from templates import second",
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
nil, // Response
|
||||
"cannot import name second", // Error
|
||||
)
|
||||
}
|
||||
|
||||
func TestWrongChartName(t *testing.T) {
|
||||
testExpansion(
|
||||
t,
|
||||
&expansion.ServiceRequest{
|
||||
ChartInvocation: &common.Resource{
|
||||
Name: "test_invocation",
|
||||
Type: getTestChartURL(),
|
||||
},
|
||||
Chart: &chart.Content{
|
||||
Chartfile: &chart.Chartfile{
|
||||
Name: "WrongName",
|
||||
Expander: jinjaExpander,
|
||||
},
|
||||
Members: []*chart.Member{
|
||||
{
|
||||
Path: "templates/main.jinja",
|
||||
Content: content([]string{"resources:"}),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
nil, // Response
|
||||
"does not match provided chart",
|
||||
)
|
||||
}
|
||||
|
||||
func TestEntrypointNotFound(t *testing.T) {
|
||||
testExpansion(
|
||||
t,
|
||||
&expansion.ServiceRequest{
|
||||
ChartInvocation: &common.Resource{
|
||||
Name: "test_invocation",
|
||||
Type: getTestChartURL(),
|
||||
},
|
||||
Chart: &chart.Content{
|
||||
Chartfile: &chart.Chartfile{
|
||||
Name: getTestChartName(t),
|
||||
Expander: jinjaExpander,
|
||||
},
|
||||
Members: []*chart.Member{},
|
||||
},
|
||||
},
|
||||
nil, // Response
|
||||
"The entrypoint in the chart.yaml cannot be found",
|
||||
)
|
||||
}
|
||||
|
||||
func TestMalformedResource(t *testing.T) {
|
||||
testExpansion(
|
||||
t,
|
||||
&expansion.ServiceRequest{
|
||||
ChartInvocation: &common.Resource{
|
||||
Name: "test_invocation",
|
||||
Type: getTestChartURL(),
|
||||
},
|
||||
Chart: &chart.Content{
|
||||
Chartfile: &chart.Chartfile{
|
||||
Name: getTestChartName(t),
|
||||
Expander: jinjaExpander,
|
||||
},
|
||||
Members: []*chart.Member{
|
||||
{
|
||||
Path: "templates/main.jinja",
|
||||
Content: content([]string{
|
||||
"resources:",
|
||||
"fail",
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
nil, // Response
|
||||
"could not found expected ':'", // [sic]
|
||||
)
|
||||
}
|
||||
|
||||
func TestResourceNoName(t *testing.T) {
|
||||
testExpansion(
|
||||
t,
|
||||
&expansion.ServiceRequest{
|
||||
ChartInvocation: &common.Resource{
|
||||
Name: "test_invocation",
|
||||
Type: getTestChartURL(),
|
||||
},
|
||||
Chart: &chart.Content{
|
||||
Chartfile: &chart.Chartfile{
|
||||
Name: getTestChartName(t),
|
||||
Expander: jinjaExpander,
|
||||
},
|
||||
Members: []*chart.Member{
|
||||
{
|
||||
Path: "templates/main.jinja",
|
||||
Content: content([]string{
|
||||
"resources:",
|
||||
"- type: bar",
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
nil, // Response.
|
||||
"Resource does not have a name",
|
||||
)
|
||||
}
|
||||
|
||||
func TestResourceNoType(t *testing.T) {
|
||||
testExpansion(
|
||||
t,
|
||||
&expansion.ServiceRequest{
|
||||
ChartInvocation: &common.Resource{
|
||||
Name: "test_invocation",
|
||||
Type: getTestChartURL(),
|
||||
},
|
||||
Chart: &chart.Content{
|
||||
Chartfile: &chart.Chartfile{
|
||||
Name: getTestChartName(t),
|
||||
Expander: jinjaExpander,
|
||||
},
|
||||
Members: []*chart.Member{
|
||||
{
|
||||
Path: "templates/main.jinja",
|
||||
Content: content([]string{
|
||||
"resources:",
|
||||
"- name: foo",
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
nil, // Response.
|
||||
"Resource does not have type defined",
|
||||
)
|
||||
}
|
||||
|
||||
func TestReplicatedService(t *testing.T) {
|
||||
replicatedService, err := chart.LoadDir("../../../examples/charts/replicatedservice")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
replicatedServiceContent, err := replicatedService.LoadContent()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
testExpansion(
|
||||
t,
|
||||
&expansion.ServiceRequest{
|
||||
ChartInvocation: &common.Resource{
|
||||
Name: "test_invocation",
|
||||
Type: "gs://kubernetes-charts-testing/replicatedservice-1.2.3.tgz",
|
||||
Properties: map[string]interface{}{
|
||||
"image": "myimage",
|
||||
"container_port": 1234,
|
||||
"replicas": 3,
|
||||
},
|
||||
},
|
||||
Chart: replicatedServiceContent,
|
||||
},
|
||||
&expansion.ServiceResponse{
|
||||
Resources: []interface{}{
|
||||
map[string]interface{}{
|
||||
"name": "test_invocation-rc",
|
||||
"properties": map[string]interface{}{
|
||||
"apiVersion": "v1",
|
||||
"kind": "ReplicationController",
|
||||
"metadata": map[string]interface{}{
|
||||
"labels": map[string]interface{}{
|
||||
"name": "test_invocation-rc",
|
||||
},
|
||||
"name": "test_invocation-rc",
|
||||
"namespace": "default",
|
||||
},
|
||||
"spec": map[string]interface{}{
|
||||
"replicas": 3.0,
|
||||
"selector": map[string]interface{}{
|
||||
"name": "test_invocation",
|
||||
},
|
||||
"template": map[string]interface{}{
|
||||
"metadata": map[string]interface{}{
|
||||
"labels": map[string]interface{}{
|
||||
"name": "test_invocation",
|
||||
},
|
||||
},
|
||||
"spec": map[string]interface{}{
|
||||
"containers": []interface{}{
|
||||
map[string]interface{}{
|
||||
"env": []interface{}{},
|
||||
"image": "myimage",
|
||||
"name": "test_invocation",
|
||||
"ports": []interface{}{
|
||||
map[string]interface{}{
|
||||
"containerPort": 1234.0,
|
||||
"name": "test_invocation",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"type": "ReplicationController",
|
||||
},
|
||||
map[string]interface{}{
|
||||
"name": "test_invocation-service",
|
||||
"properties": map[string]interface{}{
|
||||
"apiVersion": "v1",
|
||||
"kind": "Service",
|
||||
"metadata": map[string]interface{}{
|
||||
"labels": map[string]interface{}{
|
||||
"name": "test_invocation-service",
|
||||
},
|
||||
"name": "test_invocation-service",
|
||||
"namespace": "default",
|
||||
},
|
||||
"spec": map[string]interface{}{
|
||||
"ports": []interface{}{
|
||||
map[string]interface{}{
|
||||
"name": "test_invocation",
|
||||
"port": 1234.0,
|
||||
"targetPort": 1234.0,
|
||||
},
|
||||
},
|
||||
"selector": map[string]interface{}{
|
||||
"name": "test_invocation",
|
||||
},
|
||||
},
|
||||
},
|
||||
"type": "Service",
|
||||
},
|
||||
},
|
||||
},
|
||||
"", // Error.
|
||||
)
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
/*
|
||||
Copyright 2015 The Kubernetes Authors All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/kubernetes/helm/cmd/expandybird/expander"
|
||||
"github.com/kubernetes/helm/pkg/expansion"
|
||||
"github.com/kubernetes/helm/pkg/version"
|
||||
|
||||
"flag"
|
||||
"log"
|
||||
)
|
||||
|
||||
// interface that we are going to listen on
|
||||
var address = flag.String("address", "", "Interface to listen on")
|
||||
|
||||
// port that we are going to listen on
|
||||
var port = flag.Int("port", 8080, "Port to listen on")
|
||||
|
||||
// path to expansion binary
|
||||
var expansionBinary = flag.String("expansion_binary", "../../../expansion/expansion.py",
|
||||
"The path to the expansion binary that will be used to expand the template.")
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
backend := expander.NewExpander(*expansionBinary)
|
||||
service := expansion.NewService(*address, *port, backend)
|
||||
log.Printf("Version: %s", version.Version)
|
||||
log.Printf("Listening on http://%s:%d/expand", *address, *port)
|
||||
log.Fatal(service.ListenAndServe())
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
######################################################################
|
||||
# Copyright 2015 The Kubernetes Authors All rights reserved.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
# 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.
|
||||
######################################################################
|
||||
|
||||
config:
|
||||
resources:
|
||||
- name: expandybird-service
|
||||
properties:
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
labels:
|
||||
app: expandybird
|
||||
name: expandybird-service
|
||||
namespace: default
|
||||
spec:
|
||||
ports:
|
||||
- name: expandybird
|
||||
port: 8080
|
||||
targetPort: 8080
|
||||
selector:
|
||||
app: expandybird
|
||||
type: LoadBalancer
|
||||
type: Service
|
||||
- name: expandybird-rc
|
||||
properties:
|
||||
apiVersion: v1
|
||||
kind: ReplicationController
|
||||
metadata:
|
||||
labels:
|
||||
app: expandybird
|
||||
name: expandybird-rc
|
||||
namespace: default
|
||||
spec:
|
||||
replicas: 3
|
||||
selector:
|
||||
app: expandybird
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: expandybird
|
||||
spec:
|
||||
containers:
|
||||
- env: []
|
||||
image: gcr.io/kubernetes-helm/expandybird
|
||||
name: expandybird
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
name: expandybird
|
||||
type: ReplicationController
|
||||
layout:
|
||||
resources:
|
||||
- name: expandybird
|
||||
properties:
|
||||
container_port: 8080
|
||||
external_service: true
|
||||
image: gcr.io/kubernetes-helm/expandybird
|
||||
labels:
|
||||
app: expandybird
|
||||
replicas: 3
|
||||
service_port: 8080
|
||||
target_port: 8080
|
||||
resources:
|
||||
- name: expandybird-service
|
||||
type: Service
|
||||
- name: expandybird-rc
|
||||
type: ReplicationController
|
||||
type: replicatedservice.py
|
@ -1,22 +0,0 @@
|
||||
######################################################################
|
||||
# Copyright 2015 The Kubernetes Authors All rights reserved.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
# 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.
|
||||
######################################################################
|
||||
|
||||
imports:
|
||||
- path: invalidfilename.py
|
||||
resources:
|
||||
- name: expandybird
|
||||
type: replicatedservice.py
|
||||
properties:
|
||||
service_port: 8080
|
||||
target_port: 8080
|
||||
image: gcr.io/kubernetes-helm/expandybird
|
@ -1,22 +0,0 @@
|
||||
######################################################################
|
||||
# Copyright 2015 The Kubernetes Authors All rights reserved.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
# 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.
|
||||
######################################################################
|
||||
|
||||
imports:
|
||||
- path: replicatedservice.py
|
||||
resources:
|
||||
- name: expandybird
|
||||
type: replicatedservice.py
|
||||
properties:
|
||||
service_port: 8080
|
||||
target_port: 8080
|
||||
invalidproperty: gcr.io/kubernetes-helm/expandybird
|
@ -1,22 +0,0 @@
|
||||
######################################################################
|
||||
# Copyright 2015 The Kubernetes Authors All rights reserved.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
# 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.
|
||||
######################################################################
|
||||
|
||||
imports:
|
||||
- path: replicatedservice.py
|
||||
resources:
|
||||
- name: expandybird
|
||||
type: invalidtypename.py
|
||||
properties:
|
||||
service_port: 8080
|
||||
target_port: 8080
|
||||
image: gcr.io/kubernetes-helm/expandybird
|
@ -1,20 +0,0 @@
|
||||
######################################################################
|
||||
# Copyright 2015 The Kubernetes Authors All rights reserved.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
# 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.
|
||||
######################################################################
|
||||
|
||||
imports:
|
||||
- path: replicatedservice.py
|
||||
resources:
|
||||
- name: expandybird
|
||||
type: replicatedservice.py
|
||||
thisisnotalist: somevalue
|
||||
shouldnotbehere: anothervalue
|
@ -1,21 +0,0 @@
|
||||
######################################################################
|
||||
# Copyright 2015 The Kubernetes Authors All rights reserved.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
# 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.
|
||||
######################################################################
|
||||
|
||||
imports:
|
||||
resources:
|
||||
- name: expandybird
|
||||
type: replicatedservice.py
|
||||
properties:
|
||||
service_port: 8080
|
||||
target_port: 8080
|
||||
image: gcr.io/kubernetes-helm/expandybird
|
@ -1,21 +0,0 @@
|
||||
######################################################################
|
||||
# Copyright 2015 The Kubernetes Authors All rights reserved.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
# 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.
|
||||
######################################################################
|
||||
|
||||
imports:
|
||||
- path: replicatedservice.py
|
||||
resources:
|
||||
- type: replicatedservice.py
|
||||
properties:
|
||||
service_port: 8080
|
||||
target_port: 8080
|
||||
image: gcr.io/kubernetes-helm/expandybird
|
@ -1,21 +0,0 @@
|
||||
######################################################################
|
||||
# Copyright 2015 The Kubernetes Authors All rights reserved.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
# 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.
|
||||
######################################################################
|
||||
|
||||
imports:
|
||||
- path: replicatedservice.py
|
||||
resources:
|
||||
- name: expandybird
|
||||
properties:
|
||||
service_port: 8080
|
||||
target_port: 8080
|
||||
image: gcr.io/kubernetes-helm/expandybird
|
Binary file not shown.
@ -1,27 +0,0 @@
|
||||
######################################################################
|
||||
# Copyright 2015 The Kubernetes Authors All rights reserved.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
# 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.
|
||||
######################################################################
|
||||
|
||||
imports:
|
||||
- path: replicatedservice.py
|
||||
resources:
|
||||
- name: expandybird
|
||||
type: replicatedservice.py
|
||||
properties:
|
||||
service_port: 8080
|
||||
target_port: 8080
|
||||
container_port: 8080
|
||||
external_service: true
|
||||
replicas: 3
|
||||
image: gcr.io/kubernetes-helm/expandybird
|
||||
labels:
|
||||
app: expandybird
|
@ -1,182 +0,0 @@
|
||||
|
||||
######################################################################
|
||||
# Copyright 2015 The Kubernetes Authors All rights reserved.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
# 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.
|
||||
######################################################################
|
||||
|
||||
"""Defines a ReplicatedService type by creating both a Service and an RC.
|
||||
|
||||
This module creates a typical abstraction for running a service in a
|
||||
Kubernetes cluster, namely a replication controller and a service packaged
|
||||
together into a single unit.
|
||||
"""
|
||||
|
||||
import yaml
|
||||
|
||||
SERVICE_TYPE_COLLECTION = 'Service'
|
||||
RC_TYPE_COLLECTION = 'ReplicationController'
|
||||
|
||||
|
||||
def GenerateConfig(context):
|
||||
"""Generates a Replication Controller and a matching Service.
|
||||
|
||||
Args:
|
||||
context: Template context. See schema for context properties.
|
||||
|
||||
Returns:
|
||||
A Container Manifest as a YAML string.
|
||||
"""
|
||||
# YAML config that we're going to create for both RC & Service
|
||||
config = {'resources': []}
|
||||
|
||||
name = context.env['name']
|
||||
container_name = context.properties.get('container_name', name)
|
||||
namespace = context.properties.get('namespace', 'default')
|
||||
|
||||
# Define things that the Service cares about
|
||||
service_name = context.properties.get('service_name', name + '-service')
|
||||
service_type = SERVICE_TYPE_COLLECTION
|
||||
|
||||
# Define things that the Replication Controller (rc) cares about
|
||||
rc_name = name + '-rc'
|
||||
rc_type = RC_TYPE_COLLECTION
|
||||
|
||||
service = {
|
||||
'name': service_name,
|
||||
'type': service_type,
|
||||
'properties': {
|
||||
'apiVersion': 'v1',
|
||||
'kind': 'Service',
|
||||
'metadata': {
|
||||
'name': service_name,
|
||||
'namespace': namespace,
|
||||
'labels': GenerateLabels(context, service_name),
|
||||
},
|
||||
'spec': {
|
||||
'ports': [GenerateServicePorts(context, container_name)],
|
||||
'selector': GenerateLabels(context, name)
|
||||
}
|
||||
}
|
||||
}
|
||||
set_up_external_lb = context.properties.get('external_service', None)
|
||||
if set_up_external_lb:
|
||||
service['properties']['spec']['type'] = 'LoadBalancer'
|
||||
config['resources'].append(service)
|
||||
|
||||
rc = {
|
||||
'name': rc_name,
|
||||
'type': rc_type,
|
||||
'properties': {
|
||||
'apiVersion': 'v1',
|
||||
'kind': 'ReplicationController',
|
||||
'metadata': {
|
||||
'name': rc_name,
|
||||
'namespace': namespace,
|
||||
'labels': GenerateLabels(context, rc_name),
|
||||
},
|
||||
'spec': {
|
||||
'replicas': context.properties['replicas'],
|
||||
'selector': GenerateLabels(context, name),
|
||||
'template': {
|
||||
'metadata': {
|
||||
'labels': GenerateLabels(context, name),
|
||||
},
|
||||
'spec': {
|
||||
'containers': [
|
||||
{
|
||||
'env': GenerateEnv(context),
|
||||
'name': container_name,
|
||||
'image': context.properties['image'],
|
||||
'ports': [
|
||||
{
|
||||
'name': container_name,
|
||||
'containerPort': context.properties['container_port'],
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
config['resources'].append(rc)
|
||||
return yaml.dump(config)
|
||||
|
||||
|
||||
def GenerateLabels(context, name):
|
||||
"""Generates labels either from the context.properties['labels'] or
|
||||
generates a default label 'app':name
|
||||
|
||||
We make a deep copy of the context.properties['labels'] section to avoid
|
||||
linking in the yaml document, which I believe reduces readability of the
|
||||
expanded template. If no labels are given, generate a default 'app':name.
|
||||
|
||||
Args:
|
||||
context: Template context, which can contain the following properties:
|
||||
labels - Labels to generate
|
||||
|
||||
Returns:
|
||||
A dict containing labels in a name:value format
|
||||
"""
|
||||
tmp_labels = context.properties.get('labels', None)
|
||||
ret_labels = {'app': name}
|
||||
if isinstance(tmp_labels, dict):
|
||||
for key, value in tmp_labels.iteritems():
|
||||
ret_labels[key] = value
|
||||
return ret_labels
|
||||
|
||||
|
||||
def GenerateServicePorts(context, name):
|
||||
"""Generates a ports section for a service.
|
||||
|
||||
Args:
|
||||
context: Template context, which can contain the following properties:
|
||||
service_port - Port to use for the service
|
||||
target_port - Target port for the service
|
||||
protocol - Protocol to use.
|
||||
|
||||
Returns:
|
||||
A dict containing a port definition
|
||||
"""
|
||||
service_port = context.properties.get('service_port', None)
|
||||
target_port = context.properties.get('target_port', None)
|
||||
protocol = context.properties.get('protocol')
|
||||
|
||||
ports = {}
|
||||
if name:
|
||||
ports['name'] = name
|
||||
if service_port:
|
||||
ports['port'] = service_port
|
||||
if target_port:
|
||||
ports['targetPort'] = target_port
|
||||
if protocol:
|
||||
ports['protocol'] = protocol
|
||||
|
||||
return ports
|
||||
|
||||
def GenerateEnv(context):
|
||||
"""Generates environmental variables for a pod.
|
||||
|
||||
Args:
|
||||
context: Template context, which can contain the following properties:
|
||||
env - Environment variables to set.
|
||||
|
||||
Returns:
|
||||
A list containing env variables in dict format {name: 'name', value: 'value'}
|
||||
"""
|
||||
env = []
|
||||
tmp_env = context.properties.get('env', [])
|
||||
for entry in tmp_env:
|
||||
if isinstance(entry, dict):
|
||||
env.append({'name': entry.get('name'), 'value': entry.get('value')})
|
||||
return env
|
@ -1,9 +0,0 @@
|
||||
info:
|
||||
title: Schema with a lots of errors in it
|
||||
|
||||
imports:
|
||||
|
||||
properties:
|
||||
exclusiveMin:
|
||||
type: integer
|
||||
exclusiveMinimum: 0
|
@ -1,14 +0,0 @@
|
||||
info:
|
||||
title: Schema with a property that has a referenced default value
|
||||
|
||||
imports:
|
||||
|
||||
properties:
|
||||
number:
|
||||
$ref: '#/level/mult'
|
||||
|
||||
level:
|
||||
mult:
|
||||
type: integer
|
||||
multipleOf: 1
|
||||
default: 1
|
@ -1,12 +0,0 @@
|
||||
info:
|
||||
title: Schema with properties that have default values
|
||||
|
||||
imports:
|
||||
|
||||
properties:
|
||||
one:
|
||||
type: integer
|
||||
default: 1
|
||||
alpha:
|
||||
type: string
|
||||
default: alpha
|
@ -1,12 +0,0 @@
|
||||
info:
|
||||
title: Schema with properties that have default values
|
||||
|
||||
imports:
|
||||
|
||||
properties:
|
||||
one:
|
||||
type: integer
|
||||
default: 1
|
||||
alpha:
|
||||
type: string
|
||||
default: alpha
|
@ -1,11 +0,0 @@
|
||||
info:
|
||||
title: Schema with a required integer property that has a default string value
|
||||
|
||||
imports:
|
||||
|
||||
required:
|
||||
- number
|
||||
properties:
|
||||
number:
|
||||
type: integer
|
||||
default: string
|
@ -1,10 +0,0 @@
|
||||
info:
|
||||
title: Schema with references to something that doesnt exist
|
||||
|
||||
imports:
|
||||
|
||||
properties:
|
||||
odd:
|
||||
type: integer
|
||||
not:
|
||||
$ref: '#/wheeeeeee'
|
@ -1,8 +0,0 @@
|
||||
info:
|
||||
title: Schema with references to something that doesnt exist
|
||||
|
||||
imports:
|
||||
|
||||
properties:
|
||||
odd:
|
||||
$ref: '#/wheeeeeee'
|
@ -1,20 +0,0 @@
|
||||
info:
|
||||
title: Schema with properties that have extra metadata
|
||||
|
||||
imports:
|
||||
|
||||
properties:
|
||||
one:
|
||||
type: integer
|
||||
default: 1
|
||||
metadata:
|
||||
gcloud: is great!
|
||||
compute: is awesome
|
||||
alpha:
|
||||
type: string
|
||||
default: alpha
|
||||
metadata:
|
||||
- you
|
||||
- can
|
||||
- do
|
||||
- anything
|
@ -1,11 +0,0 @@
|
||||
info:
|
||||
title: Schema with references
|
||||
|
||||
imports:
|
||||
|
||||
properties:
|
||||
number:
|
||||
$ref: #/number
|
||||
|
||||
number:
|
||||
type: integer
|
@ -1,33 +0,0 @@
|
||||
info:
|
||||
title: VM with Disks
|
||||
author: Kubernetes
|
||||
description: Creates a single vm, then attaches disks to it.
|
||||
|
||||
required:
|
||||
- zone
|
||||
|
||||
properties:
|
||||
zone:
|
||||
type: string
|
||||
description: GCP zone
|
||||
default: us-central1-a
|
||||
disks:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required:
|
||||
- name
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
description: Suffix for this disk
|
||||
sizeGb:
|
||||
type: integer
|
||||
default: 100
|
||||
diskType:
|
||||
type: string
|
||||
enum:
|
||||
- pd-standard
|
||||
- pd-ssd
|
||||
default: pd-standard
|
||||
additionalProperties: false
|
@ -1,27 +0,0 @@
|
||||
info:
|
||||
title: Schema with a lots of number properties and restrictions
|
||||
|
||||
imports:
|
||||
|
||||
properties:
|
||||
minimum0:
|
||||
type: integer
|
||||
minimum: 0
|
||||
exclusiveMin0:
|
||||
type: integer
|
||||
minimum: 0
|
||||
exclusiveMinimum: true
|
||||
maximum10:
|
||||
type: integer
|
||||
maximum: 10
|
||||
exclusiveMax10:
|
||||
type: integer
|
||||
maximum: 10
|
||||
exclusiveMaximum: true
|
||||
even:
|
||||
type: integer
|
||||
multipleOf: 2
|
||||
odd:
|
||||
type: integer
|
||||
not:
|
||||
multipleOf: 2
|
@ -1,36 +0,0 @@
|
||||
info:
|
||||
title: VM with Disks
|
||||
author: Kubernetes
|
||||
description: Creates a single vm, then attaches disks to it.
|
||||
|
||||
required:
|
||||
- zone
|
||||
|
||||
properties:
|
||||
zone:
|
||||
type: string
|
||||
description: GCP zone
|
||||
default: us-central1-a
|
||||
disks:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/disk'
|
||||
|
||||
disk:
|
||||
type: object
|
||||
required:
|
||||
- name
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
description: Suffix for this disk
|
||||
sizeGb:
|
||||
type: integer
|
||||
default: 100
|
||||
diskType:
|
||||
type: string
|
||||
enum:
|
||||
- pd-standard
|
||||
- pd-ssd
|
||||
default: pd-standard
|
||||
additionalProperties: false
|
@ -1,14 +0,0 @@
|
||||
info:
|
||||
title: Schema with references
|
||||
|
||||
imports:
|
||||
|
||||
properties:
|
||||
odd:
|
||||
type: integer
|
||||
not:
|
||||
$ref: '#/even'
|
||||
|
||||
|
||||
even:
|
||||
multipleOf: 2
|
@ -1,14 +0,0 @@
|
||||
info:
|
||||
title: Schema with a required property that has a referenced default value
|
||||
|
||||
imports:
|
||||
|
||||
required:
|
||||
- number
|
||||
properties:
|
||||
number:
|
||||
$ref: '#/default_val'
|
||||
|
||||
default_val:
|
||||
type: integer
|
||||
default: my_name
|
@ -1,10 +0,0 @@
|
||||
info:
|
||||
title: Schema with a required property
|
||||
|
||||
imports:
|
||||
|
||||
required:
|
||||
- name
|
||||
properties:
|
||||
name:
|
||||
type: string
|
@ -1,11 +0,0 @@
|
||||
info:
|
||||
title: Schema with a required property that has a default value
|
||||
|
||||
imports:
|
||||
|
||||
required:
|
||||
- name
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
default: my_name
|
@ -1 +0,0 @@
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
|
@ -1,9 +0,0 @@
|
||||
resources:
|
||||
- type: compute.v1.instance
|
||||
name: my_instance
|
||||
properties:
|
||||
zone: test-zone-a
|
||||
- type: compute.v1.instance
|
||||
name: my_instance
|
||||
properties:
|
||||
zone: test-zone-b
|
@ -1,5 +0,0 @@
|
||||
resources:
|
||||
- type: compute.v1.instance
|
||||
name: B
|
||||
properties:
|
||||
zone: test-zone-b
|
@ -1,5 +0,0 @@
|
||||
resources:
|
||||
- type: compute.v1.instance
|
||||
name: C
|
||||
properties:
|
||||
zone: test-zone-c
|
@ -1,9 +0,0 @@
|
||||
resources:
|
||||
- type: compute.v1.instance
|
||||
name: my_instance
|
||||
properties:
|
||||
zone: test-zone-a
|
||||
- type: compute.v1.instance
|
||||
name: my_instance
|
||||
properties:
|
||||
zone: test-zone-b
|
@ -1,5 +0,0 @@
|
||||
imports: ["duplicate_names_in_subtemplates.jinja"]
|
||||
|
||||
resources:
|
||||
- name: subtemplate
|
||||
type: duplicate_names_in_subtemplates.jinja
|
@ -1,7 +0,0 @@
|
||||
imports: ["duplicate_names_B.jinja", "duplicate_names_C.jinja"]
|
||||
|
||||
resources:
|
||||
- name: A
|
||||
type: duplicate_names_B.jinja
|
||||
- name: B
|
||||
type: duplicate_names_C.jinja
|
@ -1,22 +0,0 @@
|
||||
config:
|
||||
resources:
|
||||
- name: B
|
||||
properties:
|
||||
zone: test-zone-b
|
||||
type: compute.v1.instance
|
||||
- name: C
|
||||
properties:
|
||||
zone: test-zone-c
|
||||
type: compute.v1.instance
|
||||
layout:
|
||||
resources:
|
||||
- name: A
|
||||
resources:
|
||||
- name: B
|
||||
type: compute.v1.instance
|
||||
type: duplicate_names_B.jinja
|
||||
- name: B
|
||||
resources:
|
||||
- name: C
|
||||
type: compute.v1.instance
|
||||
type: duplicate_names_C.jinja
|
@ -1,7 +0,0 @@
|
||||
imports: ["duplicate_names_B.jinja"]
|
||||
|
||||
resources:
|
||||
- name: A
|
||||
type: duplicate_names_B.jinja
|
||||
- name: B
|
||||
type: compute.v1.instance
|
@ -1,17 +0,0 @@
|
||||
config:
|
||||
resources:
|
||||
- name: B
|
||||
properties:
|
||||
zone: test-zone-b
|
||||
type: compute.v1.instance
|
||||
- name: B
|
||||
type: compute.v1.instance
|
||||
layout:
|
||||
resources:
|
||||
- name: A
|
||||
resources:
|
||||
- name: B
|
||||
type: compute.v1.instance
|
||||
type: duplicate_names_B.jinja
|
||||
- name: B
|
||||
type: compute.v1.instance
|
@ -1,5 +0,0 @@
|
||||
resources:
|
||||
- name: helper
|
||||
type: bar
|
||||
properties:
|
||||
test: {{ properties["foobar"] }}
|
@ -1,4 +0,0 @@
|
||||
properties:
|
||||
foobar:
|
||||
type: string
|
||||
default: Use this schema
|
@ -1,3 +0,0 @@
|
||||
{%- macro GenerateMachineName(prefix='', suffix='') -%}
|
||||
{{ prefix + "-" + suffix }}
|
||||
{%- endmacro %}
|
@ -1,6 +0,0 @@
|
||||
"""Dummy helper methods invoked in other constructors."""
|
||||
|
||||
|
||||
def GenerateMachineName(prefix, suffix):
|
||||
"""Generates name of a VM."""
|
||||
return prefix + "-" + suffix
|
@ -1 +0,0 @@
|
||||
"""Package marker file."""
|
@ -1,6 +0,0 @@
|
||||
"""Dummy helper methods invoked in other constructors."""
|
||||
|
||||
|
||||
def GenerateMachineSize():
|
||||
"""Generates size of a VM."""
|
||||
return "big"
|
@ -1,2 +0,0 @@
|
||||
resources:
|
||||
- name: foo properties: bar: baz
|
@ -1,16 +0,0 @@
|
||||
resources:
|
||||
- type: compute.v1.instance
|
||||
name: vm-created-by-cloud-config-{{ properties["deployment"] }}
|
||||
properties:
|
||||
zone: {{ properties["zone"] }}
|
||||
machineType: https://www.googleapis.com/compute/v1/projects/{{ properties["project"] }}/zones/{{ properties["zone"] }}/machineTypes/f1-micro
|
||||
disks:
|
||||
- deviceName: boot
|
||||
type: PERSISTENT
|
||||
boot: true
|
||||
autoDelete: true
|
||||
initializeParams:
|
||||
diskName: disk-created-by-cloud-config-{{ properties["deployment"] }}
|
||||
sourceImage: https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20140619
|
||||
networkInterfaces:
|
||||
- network: https://www.googleapis.com/compute/v1/projects/{{ properties["project"] }}/global/networks/default
|
@ -1,18 +0,0 @@
|
||||
info:
|
||||
title: Schema for a basic jinja template that includes default values
|
||||
|
||||
imports:
|
||||
|
||||
properties:
|
||||
foo:
|
||||
description: blah
|
||||
type: string
|
||||
zone:
|
||||
type: string
|
||||
default: test-zone
|
||||
project:
|
||||
type: string
|
||||
default: test-project
|
||||
deployment:
|
||||
type: string
|
||||
default: test-deployment
|
@ -1,9 +0,0 @@
|
||||
imports:
|
||||
- path: "jinja_defaults.jinja"
|
||||
- path: "jinja_defaults.jinja.schema"
|
||||
|
||||
resources:
|
||||
- name: jinja_defaults_name
|
||||
type: jinja_defaults.jinja
|
||||
properties:
|
||||
foo: bar
|
@ -1,29 +0,0 @@
|
||||
config:
|
||||
resources:
|
||||
- name: vm-created-by-cloud-config-test-deployment
|
||||
properties:
|
||||
disks:
|
||||
- autoDelete: true
|
||||
boot: true
|
||||
deviceName: boot
|
||||
initializeParams:
|
||||
diskName: disk-created-by-cloud-config-test-deployment
|
||||
sourceImage: https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20140619
|
||||
type: PERSISTENT
|
||||
machineType: https://www.googleapis.com/compute/v1/projects/test-project/zones/test-zone/machineTypes/f1-micro
|
||||
networkInterfaces:
|
||||
- network: https://www.googleapis.com/compute/v1/projects/test-project/global/networks/default
|
||||
zone: test-zone
|
||||
type: compute.v1.instance
|
||||
layout:
|
||||
resources:
|
||||
- name: jinja_defaults_name
|
||||
properties:
|
||||
deployment: test-deployment
|
||||
foo: bar
|
||||
project: test-project
|
||||
zone: test-zone
|
||||
resources:
|
||||
- name: vm-created-by-cloud-config-test-deployment
|
||||
type: compute.v1.instance
|
||||
type: jinja_defaults.jinja
|
@ -1,4 +0,0 @@
|
||||
Nothing here because this file should never be called.
|
||||
The validation will fail before this file is used.
|
||||
|
||||
{{% Invalid
|
@ -1,11 +0,0 @@
|
||||
info:
|
||||
title: Schema with a required property
|
||||
|
||||
imports:
|
||||
|
||||
required:
|
||||
- important
|
||||
properties:
|
||||
important:
|
||||
type: string
|
||||
|
@ -1,9 +0,0 @@
|
||||
imports:
|
||||
- path: "jinja_missing_required.jinja"
|
||||
- path: "jinja_missing_required.jinja.schema"
|
||||
|
||||
resources:
|
||||
- name: jinja_missing_required_resource_name
|
||||
type: jinja_missing_required.jinja
|
||||
properties:
|
||||
less-important: an optional property
|
@ -1,4 +0,0 @@
|
||||
Nothing here because this file should never be called.
|
||||
The validation will fail before this file is used.
|
||||
|
||||
{{% Invalid
|
@ -1,22 +0,0 @@
|
||||
info:
|
||||
title: Schema with several rules
|
||||
|
||||
imports:
|
||||
|
||||
properties:
|
||||
number:
|
||||
type: integer
|
||||
short-string:
|
||||
type: string
|
||||
maxLength: 10
|
||||
odd:
|
||||
type: integer
|
||||
not:
|
||||
multipleOf: 2
|
||||
abc:
|
||||
type: string
|
||||
enum:
|
||||
- a
|
||||
- b
|
||||
- c
|
||||
|
@ -1,12 +0,0 @@
|
||||
imports:
|
||||
- path: "jinja_multiple_errors.jinja"
|
||||
- path: "jinja_multiple_errors.jinja.schema"
|
||||
|
||||
resources:
|
||||
- name: jinja_multiple_errors
|
||||
type: jinja_multiple_errors.jinja
|
||||
properties:
|
||||
number: a string
|
||||
short-string: longer than 10 chars
|
||||
odd: 6
|
||||
abc: d
|
@ -1,19 +0,0 @@
|
||||
resources:
|
||||
{% for name in ['name1', 'name2'] %}
|
||||
- type: compute.v1.instance
|
||||
name: {{ name }}
|
||||
properties:
|
||||
zone: test-zone
|
||||
machineType: https://www.googleapis.com/compute/v1/projects/test-project/zones/test-zone/machineTypes/f1-micro
|
||||
disks:
|
||||
- deviceName: boot
|
||||
type: PERSISTENT
|
||||
boot: true
|
||||
autoDelete: true
|
||||
initializeParams:
|
||||
diskName: disk-created-by-cloud-config-test-deployment
|
||||
sourceImage: https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20140619
|
||||
networkInterfaces:
|
||||
- network: https://www.googleapis.com/compute/v1/projects/test-project/global/networks/default
|
||||
{% endfor %}
|
||||
|
@ -1,6 +0,0 @@
|
||||
imports: ["jinja_noparams.jinja"]
|
||||
|
||||
resources:
|
||||
- name: jinja_noparams_name
|
||||
type: jinja_noparams.jinja
|
||||
|
@ -1,41 +0,0 @@
|
||||
config:
|
||||
resources:
|
||||
- name: name1
|
||||
properties:
|
||||
disks:
|
||||
- autoDelete: true
|
||||
boot: true
|
||||
deviceName: boot
|
||||
initializeParams:
|
||||
diskName: disk-created-by-cloud-config-test-deployment
|
||||
sourceImage: https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20140619
|
||||
type: PERSISTENT
|
||||
machineType: https://www.googleapis.com/compute/v1/projects/test-project/zones/test-zone/machineTypes/f1-micro
|
||||
networkInterfaces:
|
||||
- network: https://www.googleapis.com/compute/v1/projects/test-project/global/networks/default
|
||||
zone: test-zone
|
||||
type: compute.v1.instance
|
||||
- name: name2
|
||||
properties:
|
||||
disks:
|
||||
- autoDelete: true
|
||||
boot: true
|
||||
deviceName: boot
|
||||
initializeParams:
|
||||
diskName: disk-created-by-cloud-config-test-deployment
|
||||
sourceImage: https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20140619
|
||||
type: PERSISTENT
|
||||
machineType: https://www.googleapis.com/compute/v1/projects/test-project/zones/test-zone/machineTypes/f1-micro
|
||||
networkInterfaces:
|
||||
- network: https://www.googleapis.com/compute/v1/projects/test-project/global/networks/default
|
||||
zone: test-zone
|
||||
type: compute.v1.instance
|
||||
layout:
|
||||
resources:
|
||||
- name: jinja_noparams_name
|
||||
resources:
|
||||
- name: name1
|
||||
type: compute.v1.instance
|
||||
- name: name2
|
||||
type: compute.v1.instance
|
||||
type: jinja_noparams.jinja
|
@ -1,18 +0,0 @@
|
||||
resources:
|
||||
- type: compute.v1.instance
|
||||
name: vm-created-by-cloud-config-{{ properties["deployment"] }}
|
||||
properties:
|
||||
zone: {{ properties["zone"] }}
|
||||
machineType: https://www.googleapis.com/compute/v1/projects/{{ properties["project"] }}/zones/{{ properties["zone"] }}/machineTypes/f1-micro
|
||||
disks:
|
||||
- deviceName: boot
|
||||
type: PERSISTENT
|
||||
boot: true
|
||||
autoDelete: true
|
||||
initializeParams:
|
||||
diskName: disk-created-by-cloud-config-{{ properties["deployment"] }}
|
||||
sourceImage: https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20140619
|
||||
networkInterfaces:
|
||||
- network: https://www.googleapis.com/compute/v1/projects/{{ properties["project"] }}/global/networks/default
|
||||
|
||||
|
@ -1,10 +0,0 @@
|
||||
imports: ["jinja_template.jinja"]
|
||||
|
||||
resources:
|
||||
- name: jinja_template_name
|
||||
type: jinja_template.jinja
|
||||
properties:
|
||||
zone: test-zone
|
||||
project: test-project
|
||||
deployment: test-deployment
|
||||
|
@ -1,28 +0,0 @@
|
||||
config:
|
||||
resources:
|
||||
- name: vm-created-by-cloud-config-test-deployment
|
||||
properties:
|
||||
disks:
|
||||
- autoDelete: true
|
||||
boot: true
|
||||
deviceName: boot
|
||||
initializeParams:
|
||||
diskName: disk-created-by-cloud-config-test-deployment
|
||||
sourceImage: https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20140619
|
||||
type: PERSISTENT
|
||||
machineType: https://www.googleapis.com/compute/v1/projects/test-project/zones/test-zone/machineTypes/f1-micro
|
||||
networkInterfaces:
|
||||
- network: https://www.googleapis.com/compute/v1/projects/test-project/global/networks/default
|
||||
zone: test-zone
|
||||
type: compute.v1.instance
|
||||
layout:
|
||||
resources:
|
||||
- name: jinja_template_name
|
||||
properties:
|
||||
deployment: test-deployment
|
||||
project: test-project
|
||||
zone: test-zone
|
||||
resources:
|
||||
- name: vm-created-by-cloud-config-test-deployment
|
||||
type: compute.v1.instance
|
||||
type: jinja_template.jinja
|
@ -1,18 +0,0 @@
|
||||
resources:
|
||||
- type: compute.v1.instance
|
||||
name: vm-created-by-cloud-config-{{ env["deployment"] }}
|
||||
properties:
|
||||
zone: {{ properties["zone"] }}
|
||||
machineType: https://www.googleapis.com/compute/v1/projects/{{ env["project"] }}/zones/{{ properties["zone"] }}/machineTypes/f1-micro
|
||||
disks:
|
||||
- deviceName: boot
|
||||
type: PERSISTENT
|
||||
boot: true
|
||||
autoDelete: true
|
||||
initializeParams:
|
||||
diskName: disk-created-by-cloud-config-{{ env["deployment"] }}-{{ env["name"] }}-{{ env["type"] }}
|
||||
sourceImage: https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20140619
|
||||
networkInterfaces:
|
||||
- network: https://www.googleapis.com/compute/v1/projects/{{ env["project"] }}/global/networks/default
|
||||
|
||||
|
@ -1,8 +0,0 @@
|
||||
imports: ["jinja_template_with_env.jinja"]
|
||||
|
||||
resources:
|
||||
- name: jinja_template_with_env_name
|
||||
type: jinja_template_with_env.jinja
|
||||
properties:
|
||||
zone: test-zone
|
||||
|
@ -1,26 +0,0 @@
|
||||
config:
|
||||
resources:
|
||||
- name: vm-created-by-cloud-config-test-deployment
|
||||
properties:
|
||||
disks:
|
||||
- autoDelete: true
|
||||
boot: true
|
||||
deviceName: boot
|
||||
initializeParams:
|
||||
diskName: disk-created-by-cloud-config-test-deployment-jinja_template_with_env_name-jinja_template_with_env.jinja
|
||||
sourceImage: https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20140619
|
||||
type: PERSISTENT
|
||||
machineType: https://www.googleapis.com/compute/v1/projects/test-project/zones/test-zone/machineTypes/f1-micro
|
||||
networkInterfaces:
|
||||
- network: https://www.googleapis.com/compute/v1/projects/test-project/global/networks/default
|
||||
zone: test-zone
|
||||
type: compute.v1.instance
|
||||
layout:
|
||||
resources:
|
||||
- name: jinja_template_with_env_name
|
||||
properties:
|
||||
zone: test-zone
|
||||
resources:
|
||||
- name: vm-created-by-cloud-config-test-deployment
|
||||
type: compute.v1.instance
|
||||
type: jinja_template_with_env.jinja
|
@ -1,6 +0,0 @@
|
||||
{% import 'helpers/common.jinja' as common %}
|
||||
resources:
|
||||
- name: {{ common.GenerateMachineName("myFrontend", "prod") }}
|
||||
type: compute.v1.instance
|
||||
properties:
|
||||
machineSize: big
|
@ -1,5 +0,0 @@
|
||||
imports: ["jinja_template_with_import.jinja", "helpers/common.jinja"]
|
||||
|
||||
resources:
|
||||
- name: jinja_template_with_import_name
|
||||
type: jinja_template_with_import.jinja
|
@ -1,13 +0,0 @@
|
||||
config:
|
||||
resources:
|
||||
- name: myFrontend-prod
|
||||
properties:
|
||||
machineSize: big
|
||||
type: compute.v1.instance
|
||||
layout:
|
||||
resources:
|
||||
- name: jinja_template_with_import_name
|
||||
resources:
|
||||
- name: myFrontend-prod
|
||||
type: compute.v1.instance
|
||||
type: jinja_template_with_import.jinja
|
@ -1,7 +0,0 @@
|
||||
{% import 'helpers/common.jinja' as common %}
|
||||
resources:
|
||||
- name: {{ common.GenerateMachineName("myFrontend", "prod") }}
|
||||
type: compute.v1.instance
|
||||
properties:
|
||||
description: {{ imports[properties["description-file"]] }}
|
||||
machineSize: big
|
@ -1,7 +0,0 @@
|
||||
imports: ["jinja_template_with_inlinedfile.jinja", "helpers/common.jinja", "description_text.txt"]
|
||||
|
||||
resources:
|
||||
- name: jinja_template_with_inlinedfile_name
|
||||
type: jinja_template_with_inlinedfile.jinja
|
||||
properties:
|
||||
description-file: description_text.txt
|
@ -1,21 +0,0 @@
|
||||
config:
|
||||
resources:
|
||||
- name: myFrontend-prod
|
||||
properties:
|
||||
description: Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
|
||||
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
|
||||
veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
|
||||
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
|
||||
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat
|
||||
non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
machineSize: big
|
||||
type: compute.v1.instance
|
||||
layout:
|
||||
resources:
|
||||
- name: jinja_template_with_inlinedfile_name
|
||||
properties:
|
||||
description-file: description_text.txt
|
||||
resources:
|
||||
- name: myFrontend-prod
|
||||
type: compute.v1.instance
|
||||
type: jinja_template_with_inlinedfile.jinja
|
@ -1,18 +0,0 @@
|
||||
resources:
|
||||
- type: compute.v1.instance
|
||||
name: vm-created-by-cloud-config-{{ porcelain["deployment"] }}
|
||||
properties:
|
||||
zone: {{ properties["zone"] }}
|
||||
machineType: https://www.googleapis.com/compute/v1/projects/{{ properties["project"] }}/zones/{{ properties["zone"] }}/machineTypes/f1-micro
|
||||
disks:
|
||||
- deviceName: boot
|
||||
type: PERSISTENT
|
||||
boot: true
|
||||
autoDelete: true
|
||||
initializeParams:
|
||||
diskName: disk-created-by-cloud-config-{{ properties["deployment"] }}
|
||||
sourceImage: https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20140619
|
||||
networkInterfaces:
|
||||
- network: https://www.googleapis.com/compute/v1/projects/{{ properties["project"] }}/global/networks/default
|
||||
|
||||
|
@ -1,10 +0,0 @@
|
||||
imports: ["jinja_unresolved.jinja"]
|
||||
|
||||
resources:
|
||||
- name: jinja_template_name
|
||||
type: jinja_unresolved.jinja
|
||||
properties:
|
||||
zone: test-zone
|
||||
project: test-project
|
||||
deployment: test-deployment
|
||||
|
@ -1,5 +0,0 @@
|
||||
"""Return empty resources block."""
|
||||
|
||||
|
||||
def GenerateConfig(_):
|
||||
return """resources:"""
|
@ -1,6 +0,0 @@
|
||||
imports:
|
||||
- path: "no_properties.py"
|
||||
|
||||
resources:
|
||||
- name: test-resource
|
||||
type: no_properties.py
|
@ -1,6 +0,0 @@
|
||||
config:
|
||||
resources: []
|
||||
layout:
|
||||
resources:
|
||||
- name: test-resource
|
||||
type: no_properties.py
|
@ -1,6 +0,0 @@
|
||||
"""Does nothing."""
|
||||
|
||||
|
||||
def GenerateConfig(_):
|
||||
"""Returns empty string."""
|
||||
return ''
|
@ -1,6 +0,0 @@
|
||||
imports:
|
||||
- path: "no_resources.py"
|
||||
|
||||
resources:
|
||||
- name: test-resource
|
||||
type: no_resources.py
|
@ -1,17 +0,0 @@
|
||||
resources:
|
||||
- type: compute.v1.instance
|
||||
name: vm-created-by-cloud-config-{{ properties["deployment"] }}
|
||||
properties:
|
||||
zone: {{ properties["zone"] }}
|
||||
machineType: https://www.googleapis.com/compute/v1/projects/{{ properties["project"] }}/zones/{{ properties["zone"] }}/machineTypes/f1-micro
|
||||
disks:
|
||||
- deviceName: boot
|
||||
type: PERSISTENT
|
||||
boot: true
|
||||
autoDelete: true
|
||||
initializeParams:
|
||||
diskName: disk-created-by-cloud-config-{{ properties["deployment"] }}
|
||||
sourceImage: https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20140619
|
||||
networkInterfaces:
|
||||
- network: https://www.googleapis.com/compute/v1/projects/{{ properties["project"] }}/global/networks/default
|
||||
|
@ -1,35 +0,0 @@
|
||||
#% description: Creates a VM running a Salt master daemon in a Docker container.
|
||||
#% parameters:
|
||||
#% - name: masterAddress
|
||||
#% type: string
|
||||
#% description: Name of the Salt master VM.
|
||||
#% required: true
|
||||
#% - name: project
|
||||
#% type: string
|
||||
#% description: Name of the Cloud project.
|
||||
#% required: true
|
||||
#% - name: zone
|
||||
#% type: string
|
||||
#% description: Zone to create the resources in.
|
||||
#% required: true
|
||||
|
||||
"""Generates config for a VM running a SaltStack master.
|
||||
|
||||
Just for fun this template is in Python, while the others in this
|
||||
directory are in Jinja2.
|
||||
"""
|
||||
|
||||
|
||||
def GenerateConfig(evaluation_context):
|
||||
return """
|
||||
resources:
|
||||
- name: python_and_jinja_template_jinja_name
|
||||
type: python_and_jinja_template.jinja
|
||||
properties:
|
||||
zone: %(zone)s
|
||||
project: %(project)s
|
||||
deployment: %(master)s
|
||||
|
||||
""" % {"master": evaluation_context.properties["masterAddress"],
|
||||
"project": evaluation_context.properties["project"],
|
||||
"zone": evaluation_context.properties["zone"]}
|
@ -1,9 +0,0 @@
|
||||
imports: ["python_and_jinja_template.jinja", "python_and_jinja_template.py"]
|
||||
|
||||
resources:
|
||||
- name: python_and_jinja_template_name
|
||||
type: python_and_jinja_template.py
|
||||
properties:
|
||||
masterAddress: master-address
|
||||
project: my-project
|
||||
zone: my-zone
|
@ -1,35 +0,0 @@
|
||||
config:
|
||||
resources:
|
||||
- name: vm-created-by-cloud-config-master-address
|
||||
properties:
|
||||
disks:
|
||||
- autoDelete: true
|
||||
boot: true
|
||||
deviceName: boot
|
||||
initializeParams:
|
||||
diskName: disk-created-by-cloud-config-master-address
|
||||
sourceImage: https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20140619
|
||||
type: PERSISTENT
|
||||
machineType: https://www.googleapis.com/compute/v1/projects/my-project/zones/my-zone/machineTypes/f1-micro
|
||||
networkInterfaces:
|
||||
- network: https://www.googleapis.com/compute/v1/projects/my-project/global/networks/default
|
||||
zone: my-zone
|
||||
type: compute.v1.instance
|
||||
layout:
|
||||
resources:
|
||||
- name: python_and_jinja_template_name
|
||||
properties:
|
||||
masterAddress: master-address
|
||||
project: my-project
|
||||
zone: my-zone
|
||||
resources:
|
||||
- name: python_and_jinja_template_jinja_name
|
||||
properties:
|
||||
deployment: master-address
|
||||
project: my-project
|
||||
zone: my-zone
|
||||
resources:
|
||||
- name: vm-created-by-cloud-config-master-address
|
||||
type: compute.v1.instance
|
||||
type: python_and_jinja_template.jinja
|
||||
type: python_and_jinja_template.py
|
@ -1,3 +0,0 @@
|
||||
"""Throws an exception."""
|
||||
|
||||
raise Exception
|
@ -1,19 +0,0 @@
|
||||
info:
|
||||
title: Schema with several errors
|
||||
|
||||
imports:
|
||||
|
||||
properties:
|
||||
bad-type:
|
||||
type: int
|
||||
missing-cond:
|
||||
type: string
|
||||
exclusiveMaximum: 10
|
||||
odd-string:
|
||||
type: string
|
||||
not:
|
||||
multipleOf: 2
|
||||
bad-enum:
|
||||
type: string
|
||||
enum: not a list
|
||||
|
@ -1,9 +0,0 @@
|
||||
imports:
|
||||
- path: "python_bad_schema.py"
|
||||
- path: "python_bad_schema.py.schema"
|
||||
|
||||
resources:
|
||||
- name: python_bad_schema
|
||||
type: python_bad_schema.py
|
||||
properties:
|
||||
innocent: true
|
@ -1,12 +0,0 @@
|
||||
"""Constructs a VM."""
|
||||
|
||||
|
||||
def GenerateConfig(_):
|
||||
"""Generates config of a VM."""
|
||||
return """
|
||||
resources:
|
||||
- name: myBackend
|
||||
type: compute.v1.instance
|
||||
properties:
|
||||
machineSize: big
|
||||
"""
|
@ -1,9 +0,0 @@
|
||||
imports: ["python_noparams.py"]
|
||||
|
||||
resources:
|
||||
- name: myFrontend
|
||||
type: compute.v1.instance
|
||||
properties:
|
||||
machineSize: big
|
||||
- name: python_noparams_name
|
||||
type: python_noparams.py
|
@ -1,19 +0,0 @@
|
||||
config:
|
||||
resources:
|
||||
- name: myFrontend
|
||||
properties:
|
||||
machineSize: big
|
||||
type: compute.v1.instance
|
||||
- name: myBackend
|
||||
properties:
|
||||
machineSize: big
|
||||
type: compute.v1.instance
|
||||
layout:
|
||||
resources:
|
||||
- name: myFrontend
|
||||
type: compute.v1.instance
|
||||
- name: python_noparams_name
|
||||
resources:
|
||||
- name: myBackend
|
||||
type: compute.v1.instance
|
||||
type: python_noparams.py
|
@ -1,57 +0,0 @@
|
||||
#% description: Creates a VM running a Salt master daemon in a Docker container.
|
||||
#% parameters:
|
||||
#% - name: masterAddress
|
||||
#% type: string
|
||||
#% description: Name of the Salt master VM.
|
||||
#% required: true
|
||||
#% - name: project
|
||||
#% type: string
|
||||
#% description: Name of the Cloud project.
|
||||
#% required: true
|
||||
#% - name: zone
|
||||
#% type: string
|
||||
#% description: Zone to create the resources in.
|
||||
#% required: true
|
||||
|
||||
"""Generates config for a VM running a SaltStack master.
|
||||
|
||||
Just for fun this template is in Python, while the others in this
|
||||
directory are in Jinja2.
|
||||
"""
|
||||
|
||||
|
||||
def GenerateConfig(evaluation_context):
|
||||
return """
|
||||
resources:
|
||||
- type: compute.v1.firewall
|
||||
name: %(master)s-firewall
|
||||
properties:
|
||||
network: https://www.googleapis.com/compute/v1/projects/%(project)s/global/networks/default
|
||||
sourceRanges: [ "0.0.0.0/0" ]
|
||||
allowed:
|
||||
- IPProtocol: tcp
|
||||
ports: [ "4505", "4506" ]
|
||||
- type: compute.v1.instance
|
||||
name: %(master)s
|
||||
properties:
|
||||
zone: %(zone)s
|
||||
machineType: https://www.googleapis.com/compute/v1/projects/%(project)s/zones/%(zone)s/machineTypes/f1-micro
|
||||
disks:
|
||||
- deviceName: boot
|
||||
type: PERSISTENT
|
||||
boot: true
|
||||
autoDelete: true
|
||||
initializeParams:
|
||||
sourceImage: https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20140619
|
||||
networkInterfaces:
|
||||
- network: https://www.googleapis.com/compute/v1/projects/%(project)s/global/networks/default
|
||||
accessConfigs:
|
||||
- name: External NAT
|
||||
type: ONE_TO_ONE_NAT
|
||||
metadata:
|
||||
items:
|
||||
- key: startup-script
|
||||
value: startup-script-value
|
||||
""" % {"master": evaluation_context.properties["masterAddress"],
|
||||
"project": evaluation_context.env["project"],
|
||||
"zone": evaluation_context.properties["zone"]}
|
@ -1,14 +0,0 @@
|
||||
info:
|
||||
title: A simple python template that has a schema.
|
||||
|
||||
imports:
|
||||
|
||||
properties:
|
||||
masterAddress:
|
||||
type: string
|
||||
default: slave-address
|
||||
description: masterAddress
|
||||
zone:
|
||||
type: string
|
||||
default: not-test-zone
|
||||
description: zone
|
@ -1,10 +0,0 @@
|
||||
imports:
|
||||
- path: "python_schema.py"
|
||||
- path: "python_schema.py.schema"
|
||||
|
||||
resources:
|
||||
- name: python_schema
|
||||
type: python_schema.py
|
||||
properties:
|
||||
masterAddress: master-address
|
||||
zone: my-zone
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue