mirror of https://github.com/helm/helm
This adds the Tiller codebase, and the revised Helm codebase. This will become the basis for continued development.pull/614/head
commit
b98d3488bc
@ -1,19 +1,6 @@
|
||||
*~
|
||||
.*.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
|
||||
.coverage/
|
||||
bin/
|
||||
rootfs/helm
|
||||
rootfs/tiller
|
||||
vendor/
|
||||
_proto/*.pb.go
|
||||
|
@ -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 +1,73 @@
|
||||
# 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
|
||||
DOCKER_REGISTRY ?= gcr.io
|
||||
IMAGE_PREFIX ?= deis-sandbox
|
||||
SHORT_NAME ?= tiller
|
||||
|
||||
# go option
|
||||
GO ?= go
|
||||
GOARCH ?= $(shell go env GOARCH)
|
||||
GOOS ?= $(shell go env GOOS)
|
||||
PKG := $(shell glide novendor)
|
||||
TAGS :=
|
||||
TESTS := .
|
||||
TESTFLAGS :=
|
||||
LDFLAGS :=
|
||||
GOFLAGS :=
|
||||
BINDIR := ./bin
|
||||
BINARIES := helm tiller
|
||||
|
||||
include versioning.mk
|
||||
|
||||
.PHONY: all
|
||||
all: build
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
$(MAKE) -C $(ROOTFS) $@
|
||||
go clean -v $(GO_PKGS)
|
||||
rm -rf bin
|
||||
.PHONY: build
|
||||
build: GOFLAGS += -a -installsuffix cgo
|
||||
build:
|
||||
@for i in $(BINARIES); do \
|
||||
CGO_ENABLED=0 GOOS=$(GOOS) GOARCH=$(GOARCH) $(GO) build -o $(BINDIR)/$$i $(GOFLAGS) -tags '$(TAGS)' -ldflags '$(LDFLAGS)' ./cmd/$$i || exit 1; \
|
||||
done
|
||||
|
||||
.PHONY: check-docker
|
||||
check-docker:
|
||||
@if [ -z $$(which docker) ]; then \
|
||||
echo "Missing \`docker\` client which is required for development"; \
|
||||
exit 2; \
|
||||
fi
|
||||
|
||||
.PHONY: docker-binary
|
||||
docker-binary: GOOS = linux
|
||||
docker-binary: GOARCH = amd64
|
||||
docker-binary: BINDIR = ./rootfs
|
||||
docker-binary: build
|
||||
|
||||
.PHONY: docker-build
|
||||
docker-build: check-docker docker-binary
|
||||
docker build --rm -t ${IMAGE} rootfs
|
||||
docker tag -f ${IMAGE} ${MUTABLE_IMAGE}
|
||||
|
||||
.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) $@
|
||||
test: build
|
||||
test: TESTFLAGS += -race -v
|
||||
test: test-style
|
||||
test: test-unit
|
||||
|
||||
.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 ----------------
|
||||
$(GO) test $(GOFLAGS) -run $(TESTS) $(PKG) $(TESTFLAGS)
|
||||
|
||||
.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: clean
|
||||
clean:
|
||||
@rm -rf $(BINDIR)
|
||||
|
||||
.PHONY: coverage
|
||||
coverage:
|
||||
@scripts/coverage.sh
|
||||
|
||||
.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 +1,38 @@
|
||||
# Helm
|
||||
# Kubernetes Helm
|
||||
|
||||
[](https://circleci.com/gh/kubernetes/helm) [](http://goreportcard.com/report/kubernetes/helm)
|
||||
Helm is a tool for managing Kubernetes charts. Charts are packages of
|
||||
pre-configured Kubernetes resources.
|
||||
|
||||
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.
|
||||
## Install
|
||||
|
||||
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:
|
||||
Helm is in its early stages of development. At this time there are no
|
||||
releases.
|
||||
|
||||
* 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?
|
||||
To install Helm from source, follow this process:
|
||||
|
||||
The official Helm repository of charts is available in the
|
||||
[kubernetes/charts](https://github.com/kubernetes/charts) repository.
|
||||
Make sure you have the prerequisites:
|
||||
- Go 1.6
|
||||
- A running Kubernetes cluster
|
||||
- `kubectl` properly configured to talk to your cluster
|
||||
- Glide 0.10 or greater
|
||||
|
||||
Please hang out with us in [the Slack chat room](https://kubernetes.slack.com/messages/helm/).
|
||||
1. Clone (or otherwise download) this repository
|
||||
2. Run `make boostrap build`
|
||||
|
||||
## Installing Helm
|
||||
You will now have two binaries built:
|
||||
|
||||
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.
|
||||
- `bin/helm` is the client
|
||||
- `bin/tiller` is the server
|
||||
|
||||
From a Linux or Mac OS X client:
|
||||
You can locally run Tiller, or you build a Docker image (`make
|
||||
docker-build`) and then deploy it (`helm init -i IMAGE_NAME`).
|
||||
|
||||
```
|
||||
$ git clone https://github.com/kubernetes/helm.git
|
||||
$ cd helm
|
||||
$ make build
|
||||
$ bin/helm server install
|
||||
```
|
||||
The [documentation](docs) folder contains more information about the
|
||||
architecture and usage of Helm/Tiller.
|
||||
|
||||
That's it. You can now use `kubectl` to see Helm running in your cluster like this:
|
||||
## The History of the Project
|
||||
|
||||
```
|
||||
$ 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.
|
||||
Kubernetes Helm is the merged result of [Helm
|
||||
Classic](https://github.com/helm/helm) and the Kubernetes port of GCS Deployment
|
||||
Manager. The project was jointly started by Google and Deis, though it
|
||||
is now part of the CNCF.
|
||||
|
@ -0,0 +1,37 @@
|
||||
space := $(empty) $(empty)
|
||||
comma := ,
|
||||
empty :=
|
||||
|
||||
import_path = github.com/kubernetes/helm/pkg/proto/hapi
|
||||
|
||||
dst = ../pkg/proto
|
||||
target = go
|
||||
plugins = grpc
|
||||
|
||||
chart_ias = $(subst $(space),$(comma),$(addsuffix =$(import_path)/$(chart_pkg),$(addprefix M,$(chart_pbs))))
|
||||
chart_pbs = $(wildcard hapi/chart/*.proto)
|
||||
chart_pkg = chart
|
||||
|
||||
release_ias = $(subst $(space),$(comma),$(addsuffix =$(import_path)/$(release_pkg),$(addprefix M,$(release_pbs))))
|
||||
release_pbs = $(wildcard hapi/release/*.proto)
|
||||
release_pkg = release
|
||||
|
||||
services_ias = $(subst $(space),$(comma),$(addsuffix =$(import_path)/$(services_pkg),$(addprefix M,$(services_pbs))))
|
||||
services_pbs = $(wildcard hapi/services/*.proto)
|
||||
services_pkg = services
|
||||
|
||||
google_deps = Mgoogle/protobuf/timestamp.proto=github.com/golang/protobuf/ptypes/timestamp,Mgoogle/protobuf/any.proto=github.com/golang/protobuf/ptypes/any
|
||||
|
||||
all: chart release services
|
||||
|
||||
chart:
|
||||
protoc --$(target)_out=plugins=$(plugins),$(google_deps),$(chart_ias):$(dst) $(chart_pbs)
|
||||
|
||||
release:
|
||||
protoc --$(target)_out=plugins=$(plugins),$(google_deps),$(chart_ias):$(dst) $(release_pbs)
|
||||
|
||||
services:
|
||||
protoc --$(target)_out=plugins=$(plugins),$(google_deps),$(chart_ias),$(release_ias):$(dst) $(services_pbs)
|
||||
|
||||
clean:
|
||||
@rm -rf $(dst)/hapi 2>/dev/null
|
@ -0,0 +1,29 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package hapi.chart;
|
||||
|
||||
import "hapi/chart/config.proto";
|
||||
import "hapi/chart/metadata.proto";
|
||||
import "hapi/chart/template.proto";
|
||||
|
||||
option go_package = "chart";
|
||||
|
||||
//
|
||||
// Chart:
|
||||
// A chart is a helm package that contains metadata, a default config, zero or more
|
||||
// optionally parameterizable templates, and zero or more charts (dependencies).
|
||||
//
|
||||
message Chart {
|
||||
// Contents of the Chartfile.
|
||||
hapi.chart.Metadata metadata = 1;
|
||||
|
||||
// Templates for this chart.
|
||||
repeated hapi.chart.Template templates = 2;
|
||||
|
||||
// Charts that this chart depends on.
|
||||
repeated Chart dependencies = 3;
|
||||
|
||||
// Default config for this template.
|
||||
hapi.chart.Config values = 4;
|
||||
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package hapi.chart;
|
||||
|
||||
option go_package = "chart";
|
||||
|
||||
//
|
||||
// Config:
|
||||
//
|
||||
// A config supplies values to the parametrizable templates of a chart.
|
||||
//
|
||||
message Config {
|
||||
string raw = 1;
|
||||
|
||||
map<string,Value> values = 2;
|
||||
}
|
||||
|
||||
//
|
||||
// Value:
|
||||
//
|
||||
// TODO
|
||||
//
|
||||
message Value {
|
||||
string value = 1;
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package hapi.chart;
|
||||
|
||||
option go_package = "chart";
|
||||
|
||||
//
|
||||
// Maintainer:
|
||||
//
|
||||
// A descriptor of the Chart maintainer(s).
|
||||
//
|
||||
message Maintainer {
|
||||
// Name is a user name or organization name
|
||||
string name = 1;
|
||||
|
||||
// Email is an optional email address to contact the named maintainer
|
||||
string email = 2;
|
||||
}
|
||||
|
||||
//
|
||||
// Metadata:
|
||||
//
|
||||
// Metadata for a Chart file. This models the structure
|
||||
// of a Chart.yaml file.
|
||||
//
|
||||
// Spec: https://github.com/kubernetes/helm/blob/master/docs/design/chart_format.md#the-chart-file
|
||||
//
|
||||
message Metadata {
|
||||
// The name of the chart
|
||||
string name = 1;
|
||||
|
||||
// The URL to a relecant project page, git repo, or contact person
|
||||
string home = 2;
|
||||
|
||||
// Source is the URL to the source code of this chart
|
||||
repeated string sources = 3;
|
||||
|
||||
// A SemVer 2 conformant version string of the chart
|
||||
string version = 4;
|
||||
|
||||
// A one-sentence description of the chart
|
||||
string description = 5;
|
||||
|
||||
// A list of string keywords
|
||||
repeated string keywords = 6;
|
||||
|
||||
// A list of name and URL/email address combinations for the maintainer(s)
|
||||
repeated Maintainer maintainers = 7;
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package hapi.chart;
|
||||
|
||||
option go_package = "chart";
|
||||
|
||||
// Template represents a template as a name/value pair.
|
||||
//
|
||||
// By convention, name is a relative path within the scope of the chart's
|
||||
// base directory.
|
||||
message Template {
|
||||
// Name is the path-like name of the template.
|
||||
string name = 1;
|
||||
|
||||
// Data is the template as byte data.
|
||||
bytes data = 2;
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package hapi.release;
|
||||
|
||||
import "google/protobuf/timestamp.proto";
|
||||
import "hapi/release/status.proto";
|
||||
|
||||
option go_package = "release";
|
||||
|
||||
//
|
||||
// Info:
|
||||
//
|
||||
//
|
||||
message Info {
|
||||
Status status = 1;
|
||||
|
||||
google.protobuf.Timestamp first_deployed = 2;
|
||||
|
||||
google.protobuf.Timestamp last_deployed = 3;
|
||||
|
||||
// Deleted tracks when this object was deleted.
|
||||
google.protobuf.Timestamp deleted = 4;
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package hapi.release;
|
||||
|
||||
import "hapi/release/info.proto";
|
||||
import "hapi/chart/config.proto";
|
||||
import "hapi/chart/chart.proto";
|
||||
|
||||
option go_package = "release";
|
||||
|
||||
//
|
||||
// Release:
|
||||
//
|
||||
// A release describes a deployment of a chart, together with the chart
|
||||
// and the variables used to deploy that chart.
|
||||
//
|
||||
message Release {
|
||||
// Name is the name of the release
|
||||
string name = 1;
|
||||
|
||||
// Info provides information about a release
|
||||
hapi.release.Info info = 2;
|
||||
|
||||
// Chart is the chart that was released.
|
||||
hapi.chart.Chart chart = 3;
|
||||
|
||||
// Config is the set of extra Values added to the chart.
|
||||
// These values override the default values inside of the chart.
|
||||
hapi.chart.Config config = 4;
|
||||
|
||||
// Manifest is the string representation of the rendered template.
|
||||
string manifest = 5;
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package hapi.release;
|
||||
|
||||
import "google/protobuf/any.proto";
|
||||
|
||||
option go_package = "release";
|
||||
|
||||
//
|
||||
// Status:
|
||||
//
|
||||
//
|
||||
message Status {
|
||||
enum Code {
|
||||
UNKNOWN = 0;
|
||||
|
||||
DEPLOYED = 1;
|
||||
|
||||
DELETED = 2;
|
||||
|
||||
SUPERSEDED = 3;
|
||||
}
|
||||
|
||||
Code code = 1;
|
||||
|
||||
google.protobuf.Any details = 2;
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package hapi.services.probe;
|
||||
|
||||
option go_package = "services";
|
||||
|
||||
service ProbeService {
|
||||
rpc Ready(ReadyRequest) returns (ReadyResponse) {
|
||||
}
|
||||
}
|
||||
|
||||
message ReadyRequest {
|
||||
}
|
||||
|
||||
message ReadyResponse {
|
||||
}
|
@ -0,0 +1,181 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package hapi.services.tiller;
|
||||
|
||||
import "hapi/chart/chart.proto";
|
||||
import "hapi/chart/config.proto";
|
||||
import "hapi/release/release.proto";
|
||||
import "hapi/release/info.proto";
|
||||
|
||||
option go_package = "services";
|
||||
|
||||
//
|
||||
// ReleaseService:
|
||||
//
|
||||
// The service that a helm application uses to mutate,
|
||||
// query, and manage releases.
|
||||
//
|
||||
// Release: A named installation composed of a chart and
|
||||
// config. At any given time a release has one
|
||||
// chart and one config.
|
||||
//
|
||||
// Config: A config is a TOML file that supplies values
|
||||
// to the parametrizable templates of a chart.
|
||||
//
|
||||
// Chart: A chart is a helm package that contains
|
||||
// metadata, a default config, zero or more
|
||||
// optionally parameterizable templates, and
|
||||
// zero or more charts (dependencies).
|
||||
//
|
||||
//
|
||||
service ReleaseService {
|
||||
//
|
||||
// Retrieve release history. TODO: Allow filtering the set of releases by
|
||||
// release status. By default, ListAllReleases returns the releases who
|
||||
// current status is "Active".
|
||||
//
|
||||
rpc ListReleases(ListReleasesRequest) returns (stream ListReleasesResponse) {
|
||||
}
|
||||
|
||||
//
|
||||
// Retrieve status information for the specified release.
|
||||
//
|
||||
rpc GetReleaseStatus(GetReleaseStatusRequest) returns (GetReleaseStatusResponse) {
|
||||
}
|
||||
|
||||
//
|
||||
// Retrieve the release content (chart + value) for the specifed release.
|
||||
//
|
||||
rpc GetReleaseContent(GetReleaseContentRequest) returns (GetReleaseContentResponse) {
|
||||
}
|
||||
|
||||
//
|
||||
// Update release content.
|
||||
//
|
||||
rpc UpdateRelease(UpdateReleaseRequest) returns (UpdateReleaseResponse) {
|
||||
}
|
||||
|
||||
//
|
||||
// Request release install.
|
||||
//
|
||||
rpc InstallRelease(InstallReleaseRequest) returns (InstallReleaseResponse) {
|
||||
}
|
||||
|
||||
//
|
||||
// Request release deletion.
|
||||
//
|
||||
rpc UninstallRelease(UninstallReleaseRequest) returns (UninstallReleaseResponse) {
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// ListReleasesRequest:
|
||||
//
|
||||
// TODO
|
||||
//
|
||||
message ListReleasesRequest {
|
||||
// The maximum number of releases to be returned
|
||||
int64 limit = 1;
|
||||
|
||||
// The zero-based offset at which the returned release list begins
|
||||
int64 offset = 2;
|
||||
}
|
||||
|
||||
//
|
||||
// ListReleasesResponse:
|
||||
//
|
||||
// TODO
|
||||
//
|
||||
message ListReleasesResponse {
|
||||
// The expected total number of releases to be returned
|
||||
int64 count = 1;
|
||||
|
||||
// The zero-based offset at which the list is positioned
|
||||
int64 offset = 2;
|
||||
|
||||
// The total number of queryable releases
|
||||
int64 total = 3;
|
||||
|
||||
// The resulting releases
|
||||
repeated hapi.release.Release releases = 4;
|
||||
}
|
||||
|
||||
// GetReleaseStatusRequest is a request to get the status of a release.
|
||||
message GetReleaseStatusRequest {
|
||||
// Name is the name of the release
|
||||
string name = 1;
|
||||
}
|
||||
|
||||
// GetReleaseStatusResponse is the response indicating the status of the named release.
|
||||
message GetReleaseStatusResponse {
|
||||
// Name is the name of the release.
|
||||
string name = 1;
|
||||
|
||||
// Info contains information about the release.
|
||||
hapi.release.Info info = 2;
|
||||
}
|
||||
|
||||
// GetReleaseContentRequest is a request to get the contents of a release.
|
||||
message GetReleaseContentRequest {
|
||||
// The name of the release
|
||||
string name = 1;
|
||||
}
|
||||
|
||||
// GetReleaseContentResponse is a response containing the contents of a release.
|
||||
message GetReleaseContentResponse {
|
||||
// The release content
|
||||
hapi.release.Release release = 1;
|
||||
}
|
||||
|
||||
//
|
||||
// UpdateReleaseRequest:
|
||||
//
|
||||
// TODO
|
||||
//
|
||||
message UpdateReleaseRequest {
|
||||
}
|
||||
|
||||
//
|
||||
// UpdateReleaseResponse:
|
||||
//
|
||||
// TODO
|
||||
//
|
||||
message UpdateReleaseResponse {
|
||||
}
|
||||
|
||||
//
|
||||
// InstallReleaseRequest:
|
||||
//
|
||||
// TODO
|
||||
//
|
||||
message InstallReleaseRequest {
|
||||
// Chart is the protobuf representation of a chart.
|
||||
hapi.chart.Chart chart = 1;
|
||||
// Values is a string containing (unparsed) TOML values.
|
||||
hapi.chart.Config values = 2;
|
||||
// DryRun, if true, will run through the release logic, but neither create
|
||||
// a release object nor deploy to Kubernetes. The release object returned
|
||||
// in the response will be fake.
|
||||
bool dry_run = 3;
|
||||
}
|
||||
|
||||
//
|
||||
// InstallReleaseResponse:
|
||||
//
|
||||
// TODO
|
||||
//
|
||||
message InstallReleaseResponse {
|
||||
hapi.release.Release release = 1;
|
||||
}
|
||||
|
||||
// UninstallReleaseRequest represents a request to uninstall a named release.
|
||||
message UninstallReleaseRequest {
|
||||
// Name is the name of the release to delete.
|
||||
string name = 1;
|
||||
}
|
||||
|
||||
// UninstallReleaseResponse represents a successful response to an uninstall request.
|
||||
message UninstallReleaseResponse {
|
||||
// Release is the release that was marked deleted.
|
||||
hapi.release.Release release = 1;
|
||||
}
|
@ -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
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue