diff --git a/.gitignore b/.gitignore index 12b7ab7bc..b94f87b26 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ _dist/ _proto/*.pb.go bin/ rootfs/tiller +rootfs/rudder vendor/ *.exe .idea/ diff --git a/Makefile b/Makefile index 1c4952821..116452173 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,10 @@ -DOCKER_REGISTRY ?= gcr.io -IMAGE_PREFIX ?= kubernetes-helm -SHORT_NAME ?= tiller -TARGETS = darwin/amd64 linux/amd64 linux/386 linux/arm linux/arm64 linux/ppc64le windows/amd64 -DIST_DIRS = find * -type d -exec -APP = helm +DOCKER_REGISTRY ?= gcr.io +IMAGE_PREFIX ?= kubernetes-helm +SHORT_NAME ?= tiller +SHORT_NAME_RUDDER ?= rudder +TARGETS = darwin/amd64 linux/amd64 linux/386 linux/arm linux/arm64 linux/ppc64le windows/amd64 +DIST_DIRS = find * -type d -exec +APP = helm # go option GO ?= go @@ -60,12 +61,20 @@ docker-binary: BINDIR = ./rootfs docker-binary: GOFLAGS += -a -installsuffix cgo docker-binary: GOOS=linux GOARCH=amd64 CGO_ENABLED=0 $(GO) build -o $(BINDIR)/tiller $(GOFLAGS) -tags '$(TAGS)' -ldflags '$(LDFLAGS)' k8s.io/helm/cmd/tiller + GOOS=linux GOARCH=amd64 CGO_ENABLED=0 $(GO) build -o $(BINDIR)/rudder $(GOFLAGS) -tags '$(TAGS)' -ldflags '$(LDFLAGS)' k8s.io/helm/cmd/rudder .PHONY: docker-build docker-build: check-docker docker-binary docker build --rm -t ${IMAGE} rootfs docker tag ${IMAGE} ${MUTABLE_IMAGE} +.PHONY: docker-build-experimental +docker-build-experimental: check-docker docker-binary + docker build --rm -t ${IMAGE} rootfs -f rootfs/Dockerfile.experimental + docker tag ${IMAGE} ${MUTABLE_IMAGE} + docker build --rm -t ${IMAGE_RUDDER} rootfs -f rootfs/Dockerfile.rudder + docker tag ${IMAGE_RUDDER} ${MUTABLE_IMAGE_RUDDER} + .PHONY: test test: build test: TESTFLAGS += -race -v diff --git a/_proto/hapi/release/modules.proto b/_proto/hapi/release/modules.proto new file mode 100644 index 000000000..4f0709a02 --- /dev/null +++ b/_proto/hapi/release/modules.proto @@ -0,0 +1,91 @@ +syntax = "proto3"; + +package hapi.release; + +import "hapi/release/release.proto"; + +option go_package = "release"; + +service ReleaseModuleService { + rpc Version(VersionReleaseRequest) returns (VersionReleaseResponse) { + } + + // InstallRelease requests installation of a chart as a new release. + rpc InstallRelease(InstallReleaseRequest) returns (InstallReleaseResponse) { + } + + // DeleteRelease requests deletion of a named release. + rpc DeleteRelease(DeleteReleaseRequest) returns (DeleteReleaseResponse) { + } + + // RollbackRelease rolls back a release to a previous version. + rpc RollbackRelease(RollbackReleaseRequest) returns (RollbackReleaseResponse) { + } + + // UpgradeRelease updates release content. + rpc UpgradeRelease(UpgradeReleaseRequest) returns (UpgradeReleaseResponse) { + } +} + +message Result { + enum Status { + // No status set + UNKNOWN = 0; + // Operation was successful + SUCCESS = 1; + // Operation had no results (e.g. upgrade identical, rollback to same, delete non-existent) + UNCHANGED = 2; + // Operation failed + ERROR = 3; + } + string info = 1; + repeated string log = 2; +} + +message VersionReleaseRequest { +} + +message VersionReleaseResponse { + string name = 1; // The canonical name of the release module + string version = 2; // The version of the release module +} + +message InstallReleaseRequest { + hapi.release.Release release = 1; +} +message InstallReleaseResponse { + hapi.release.Release release = 1; + Result result = 2; +} + +message DeleteReleaseRequest { + hapi.release.Release release = 1; +} +message DeleteReleaseResponse { + hapi.release.Release release = 1; + Result result = 2; +} + +message UpgradeReleaseRequest{ + hapi.release.Release current = 1; + hapi.release.Release target = 2; + int64 Timeout = 3; + bool Wait = 4; + bool Recreate = 5; +} +message UpgradeReleaseResponse{ + hapi.release.Release release = 1; + Result result = 2; +} + +message RollbackReleaseRequest{ + hapi.release.Release current = 1; + hapi.release.Release target = 2; + int64 Timeout = 3; + bool Wait = 4; + bool Recreate = 5; +} +message RollbackReleaseResponse{ + hapi.release.Release release = 1; + Result result = 2; +} diff --git a/cmd/rudder/install.go b/cmd/rudder/install.go new file mode 100644 index 000000000..97d569cb4 --- /dev/null +++ b/cmd/rudder/install.go @@ -0,0 +1,132 @@ +/* +Copyright 2017 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 "k8s.io/helm/cmd/rudder" + +import ( + "bytes" + "fmt" + "strings" + + "github.com/Mirantis/k8s-appcontroller/cmd/format" + "github.com/technosophos/moniker" + "google.golang.org/grpc/grpclog" + + "k8s.io/helm/pkg/proto/hapi/chart" + "k8s.io/helm/pkg/proto/hapi/release" + "k8s.io/helm/pkg/releaseutil" +) + +type Dependency struct { + Name string + Child string + Parent string +} + +func (d Dependency) String() string { + return fmt.Sprintf(`apiVersion: appcontroller.k8s/v1alpha1 +kind: Dependency +metadata: + name: %s +parent: %s +child: %s`, d.Name, d.Parent, d.Child) +} + +func wrapManifest(r *release.Release) (*bytes.Buffer, error) { + b := bytes.NewBuffer(nil) + var err error + sep := "\n---\n" + + manifests, err := releaseutil.SplitManifestsWithHeads(r.Manifest) + if err != nil { + grpclog.Printf("Could not split manifest") + return nil, err + } + + for _, m := range manifests { + grpclog.Printf("Trying to wrap %s", m.Metadata.Name) + wrapped, err := format.Yaml{}.Wrap(getInput(m.Content, 2)) + if err != nil { + grpclog.Printf("didn't wrap %s: %s", m.Metadata.Name, err) + //TODO: should we return b here? + return nil, err + } + grpclog.Printf("wrapped %s", m.Metadata.Name) + b.WriteString(wrapped) + b.WriteString(sep) + } + + deps := getDependencies(r.Chart, manifests) + + for _, d := range deps { + b.WriteString(d.String()) + b.WriteString(sep) + } + + return b, err +} + +func getInput(in string, indent int) string { + spaces := strings.Repeat(" ", indent) + result := spaces + strings.Replace(in, "\n", "\n"+spaces, -1) + return result + +} + +func getDependencies(ch *chart.Chart, manifests []releaseutil.Manifest) []Dependency { + dependencies := []Dependency{} + + for _, dep := range ch.Dependencies { + dependencies = append(dependencies, getDependencies(dep, manifests)...) + dependencies = append(dependencies, getInterChartDependencies(ch, dep, manifests)...) + } + + return dependencies +} + +func getInterChartDependencies(child, parent *chart.Chart, manifests []releaseutil.Manifest) []Dependency { + parentNames := []string{} + childNames := []string{} + for _, m := range manifests { + kind := m.Kind + name := m.Metadata.Name + grpclog.Printf("comparing %s and %s with %s/%s", child.Metadata.Name, parent.Metadata.Name, kind, name) + //so hacky I'm gonna cry. need to find a better way + //I had to remove first segment of helm release name for this to work (chart names were truncated from release name) + if strings.Contains(name, parent.Metadata.Name) { + grpclog.Printf("adding %s to parents", strings.ToLower(kind)+"/"+name) + parentNames = append(parentNames, strings.ToLower(kind)+"/"+name) + } + if strings.Contains(name, child.Metadata.Name) { + grpclog.Printf("adding %s to children", strings.ToLower(kind)+"/"+name) + childNames = append(childNames, strings.ToLower(kind)+"/"+name) + } + } + + deps := make([]Dependency, 0, len(parentNames)*len(childNames)) + + for _, parent := range parentNames { + for _, child := range childNames { + namer := moniker.New() + deps = append(deps, Dependency{ + Name: namer.NameSep("-"), + Child: child, + Parent: parent, + }) + } + } + return deps +} diff --git a/cmd/rudder/rudder.go b/cmd/rudder/rudder.go new file mode 100644 index 000000000..62461aaee --- /dev/null +++ b/cmd/rudder/rudder.go @@ -0,0 +1,99 @@ +/* +Copyright 2017 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 "k8s.io/helm/cmd/rudder" + +import ( + "bytes" + "fmt" + "net" + + "golang.org/x/net/context" + "google.golang.org/grpc" + "google.golang.org/grpc/grpclog" + + "k8s.io/helm/pkg/kube" + "k8s.io/helm/pkg/proto/hapi/release" + "k8s.io/helm/pkg/rudder" + "k8s.io/helm/pkg/version" +) + +var kubeClient = kube.New(nil) + +func main() { + lis, err := net.Listen("tcp", fmt.Sprintf(":%d", rudder.GrpcPort)) + if err != nil { + grpclog.Fatalf("failed to listen: %v", err) + } + grpcServer := grpc.NewServer() + release.RegisterReleaseModuleServiceServer(grpcServer, &ReleaseModuleServiceServer{}) + + grpclog.Print("Server starting") + grpcServer.Serve(lis) + grpclog.Print("Server started") +} + +// ReleaseModuleServiceServer provides implementation for release.ReleaseModuleServiceServer +type ReleaseModuleServiceServer struct{} + +// Version is not yet implemented +func (r *ReleaseModuleServiceServer) Version(ctx context.Context, in *release.VersionReleaseRequest) (*release.VersionReleaseResponse, error) { + grpclog.Print("version") + return &release.VersionReleaseResponse{ + Name: "helm-rudder-native", + Version: version.Version, + }, nil +} + +// InstallRelease creates a release using kubeClient.Create +func (r *ReleaseModuleServiceServer) InstallRelease(ctx context.Context, in *release.InstallReleaseRequest) (*release.InstallReleaseResponse, error) { + grpclog.Print("install") + + b, err := wrapManifest(in.Release) + if err != nil { + grpclog.Printf("error wrapping release: %s", err) + } + err = kubeClient.Create(in.Release.Namespace, b, 500, false) + if err != nil { + grpclog.Printf("error when creating release: %s", err) + } + return &release.InstallReleaseResponse{}, err +} + +// DeleteRelease is not implemented +func (r *ReleaseModuleServiceServer) DeleteRelease(ctx context.Context, in *release.DeleteReleaseRequest) (*release.DeleteReleaseResponse, error) { + grpclog.Print("delete") + return nil, nil +} + +// RollbackRelease is not implemented +func (r *ReleaseModuleServiceServer) RollbackRelease(ctx context.Context, in *release.RollbackReleaseRequest) (*release.RollbackReleaseResponse, error) { + grpclog.Print("rollback") + c := bytes.NewBufferString(in.Current.Manifest) + t := bytes.NewBufferString(in.Target.Manifest) + err := kubeClient.Update(in.Target.Namespace, c, t, in.Recreate, in.Timeout, in.Wait) + return &release.RollbackReleaseResponse{}, err +} + +// UpgradeRelease upgrades manifests using kubernetes client +func (r *ReleaseModuleServiceServer) UpgradeRelease(ctx context.Context, in *release.UpgradeReleaseRequest) (*release.UpgradeReleaseResponse, error) { + grpclog.Print("upgrade") + c := bytes.NewBufferString(in.Current.Manifest) + t := bytes.NewBufferString(in.Target.Manifest) + err := kubeClient.Update(in.Target.Namespace, c, t, in.Recreate, in.Timeout, in.Wait) + // upgrade response object should be changed to include status + return &release.UpgradeReleaseResponse{}, err +} diff --git a/cmd/tiller/tiller.go b/cmd/tiller/tiller.go index 72388d307..e7f16ba69 100644 --- a/cmd/tiller/tiller.go +++ b/cmd/tiller/tiller.go @@ -52,11 +52,12 @@ var rootServer = tiller.NewServer() var env = environment.New() var ( - grpcAddr = ":44134" - probeAddr = ":44135" - traceAddr = ":44136" - enableTracing = false - store = storageConfigMap + grpcAddr = ":44134" + probeAddr = ":44135" + traceAddr = ":44136" + enableTracing = false + store = storageConfigMap + remoteReleaseModules = false ) const globalUsage = `The Kubernetes Helm server. @@ -82,6 +83,7 @@ func main() { p.StringVarP(&grpcAddr, "listen", "l", ":44134", "address:port to listen on") p.StringVar(&store, "storage", storageConfigMap, "storage driver to use. One of 'configmap' or 'memory'") p.BoolVar(&enableTracing, "trace", false, "enable rpc tracing") + p.BoolVar(&remoteReleaseModules, "experimental-release", false, "enable experimental release modules") if err := rootCommand.Execute(); err != nil { fmt.Fprint(os.Stderr, err) @@ -121,7 +123,7 @@ func start(c *cobra.Command, args []string) { srvErrCh := make(chan error) probeErrCh := make(chan error) go func() { - svc := tiller.NewReleaseServer(env, clientset) + svc := tiller.NewReleaseServer(env, clientset, remoteReleaseModules) services.RegisterReleaseServiceServer(rootServer, svc) if err := rootServer.Serve(lstn); err != nil { srvErrCh <- err diff --git a/glide.lock b/glide.lock index 9672f8c0d..84991da55 100644 --- a/glide.lock +++ b/glide.lock @@ -501,6 +501,10 @@ imports: - third_party/forked/golang/netutil - third_party/forked/golang/reflect - third_party/forked/golang/template +- name: github.com/Mirantis/k8s-appcontroller + version: cfc62d2de68d9e7f52c9c84f976dc93502bf59ab + subpackages: + - cmd/format testImports: - name: github.com/pmezard/go-difflib version: d8ed2627bdf02c080bf22230dbb337003b7aba2d diff --git a/glide.yaml b/glide.yaml index f8a7af4f4..6ec44221b 100644 --- a/glide.yaml +++ b/glide.yaml @@ -69,3 +69,5 @@ import: version: ~0.1.0 - package: github.com/naoina/go-stringutil version: ~0.1.0 +- package: github.com/Mirantis/k8s-appcontroller + version: ~0.5.0 diff --git a/pkg/proto/hapi/release/hook.pb.go b/pkg/proto/hapi/release/hook.pb.go index 956ca15f3..da3a34438 100644 --- a/pkg/proto/hapi/release/hook.pb.go +++ b/pkg/proto/hapi/release/hook.pb.go @@ -8,6 +8,7 @@ Package release is a generated protocol buffer package. It is generated from these files: hapi/release/hook.proto hapi/release/info.proto + hapi/release/modules.proto hapi/release/release.proto hapi/release/status.proto hapi/release/test_run.proto @@ -16,6 +17,17 @@ It is generated from these files: It has these top-level messages: Hook Info + Result + VersionReleaseRequest + VersionReleaseResponse + InstallReleaseRequest + InstallReleaseResponse + DeleteReleaseRequest + DeleteReleaseResponse + UpgradeReleaseRequest + UpgradeReleaseResponse + RollbackReleaseRequest + RollbackReleaseResponse Release Status TestRun diff --git a/pkg/proto/hapi/release/modules.pb.go b/pkg/proto/hapi/release/modules.pb.go new file mode 100644 index 000000000..fa627f42b --- /dev/null +++ b/pkg/proto/hapi/release/modules.pb.go @@ -0,0 +1,526 @@ +// Code generated by protoc-gen-go. +// source: hapi/release/modules.proto +// DO NOT EDIT! + +package release + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +import ( + context "golang.org/x/net/context" + grpc "google.golang.org/grpc" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +type Result_Status int32 + +const ( + // No status set + Result_UNKNOWN Result_Status = 0 + // Operation was successful + Result_SUCCESS Result_Status = 1 + // Operation had no results (e.g. upgrade identical, rollback to same, delete non-existent) + Result_UNCHANGED Result_Status = 2 + // Operation failed + Result_ERROR Result_Status = 3 +) + +var Result_Status_name = map[int32]string{ + 0: "UNKNOWN", + 1: "SUCCESS", + 2: "UNCHANGED", + 3: "ERROR", +} +var Result_Status_value = map[string]int32{ + "UNKNOWN": 0, + "SUCCESS": 1, + "UNCHANGED": 2, + "ERROR": 3, +} + +func (x Result_Status) String() string { + return proto.EnumName(Result_Status_name, int32(x)) +} +func (Result_Status) EnumDescriptor() ([]byte, []int) { return fileDescriptor2, []int{0, 0} } + +type Result struct { + Info string `protobuf:"bytes,1,opt,name=info" json:"info,omitempty"` + Log []string `protobuf:"bytes,2,rep,name=log" json:"log,omitempty"` +} + +func (m *Result) Reset() { *m = Result{} } +func (m *Result) String() string { return proto.CompactTextString(m) } +func (*Result) ProtoMessage() {} +func (*Result) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{0} } + +type VersionReleaseRequest struct { +} + +func (m *VersionReleaseRequest) Reset() { *m = VersionReleaseRequest{} } +func (m *VersionReleaseRequest) String() string { return proto.CompactTextString(m) } +func (*VersionReleaseRequest) ProtoMessage() {} +func (*VersionReleaseRequest) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{1} } + +type VersionReleaseResponse struct { + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + Version string `protobuf:"bytes,2,opt,name=version" json:"version,omitempty"` +} + +func (m *VersionReleaseResponse) Reset() { *m = VersionReleaseResponse{} } +func (m *VersionReleaseResponse) String() string { return proto.CompactTextString(m) } +func (*VersionReleaseResponse) ProtoMessage() {} +func (*VersionReleaseResponse) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{2} } + +type InstallReleaseRequest struct { + Release *Release `protobuf:"bytes,1,opt,name=release" json:"release,omitempty"` +} + +func (m *InstallReleaseRequest) Reset() { *m = InstallReleaseRequest{} } +func (m *InstallReleaseRequest) String() string { return proto.CompactTextString(m) } +func (*InstallReleaseRequest) ProtoMessage() {} +func (*InstallReleaseRequest) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{3} } + +func (m *InstallReleaseRequest) GetRelease() *Release { + if m != nil { + return m.Release + } + return nil +} + +type InstallReleaseResponse struct { + Release *Release `protobuf:"bytes,1,opt,name=release" json:"release,omitempty"` + Result *Result `protobuf:"bytes,2,opt,name=result" json:"result,omitempty"` +} + +func (m *InstallReleaseResponse) Reset() { *m = InstallReleaseResponse{} } +func (m *InstallReleaseResponse) String() string { return proto.CompactTextString(m) } +func (*InstallReleaseResponse) ProtoMessage() {} +func (*InstallReleaseResponse) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{4} } + +func (m *InstallReleaseResponse) GetRelease() *Release { + if m != nil { + return m.Release + } + return nil +} + +func (m *InstallReleaseResponse) GetResult() *Result { + if m != nil { + return m.Result + } + return nil +} + +type DeleteReleaseRequest struct { + Release *Release `protobuf:"bytes,1,opt,name=release" json:"release,omitempty"` +} + +func (m *DeleteReleaseRequest) Reset() { *m = DeleteReleaseRequest{} } +func (m *DeleteReleaseRequest) String() string { return proto.CompactTextString(m) } +func (*DeleteReleaseRequest) ProtoMessage() {} +func (*DeleteReleaseRequest) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{5} } + +func (m *DeleteReleaseRequest) GetRelease() *Release { + if m != nil { + return m.Release + } + return nil +} + +type DeleteReleaseResponse struct { + Release *Release `protobuf:"bytes,1,opt,name=release" json:"release,omitempty"` + Result *Result `protobuf:"bytes,2,opt,name=result" json:"result,omitempty"` +} + +func (m *DeleteReleaseResponse) Reset() { *m = DeleteReleaseResponse{} } +func (m *DeleteReleaseResponse) String() string { return proto.CompactTextString(m) } +func (*DeleteReleaseResponse) ProtoMessage() {} +func (*DeleteReleaseResponse) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{6} } + +func (m *DeleteReleaseResponse) GetRelease() *Release { + if m != nil { + return m.Release + } + return nil +} + +func (m *DeleteReleaseResponse) GetResult() *Result { + if m != nil { + return m.Result + } + return nil +} + +type UpgradeReleaseRequest struct { + Current *Release `protobuf:"bytes,1,opt,name=current" json:"current,omitempty"` + Target *Release `protobuf:"bytes,2,opt,name=target" json:"target,omitempty"` + Timeout int64 `protobuf:"varint,3,opt,name=Timeout" json:"Timeout,omitempty"` + Wait bool `protobuf:"varint,4,opt,name=Wait" json:"Wait,omitempty"` + Recreate bool `protobuf:"varint,5,opt,name=Recreate" json:"Recreate,omitempty"` +} + +func (m *UpgradeReleaseRequest) Reset() { *m = UpgradeReleaseRequest{} } +func (m *UpgradeReleaseRequest) String() string { return proto.CompactTextString(m) } +func (*UpgradeReleaseRequest) ProtoMessage() {} +func (*UpgradeReleaseRequest) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{7} } + +func (m *UpgradeReleaseRequest) GetCurrent() *Release { + if m != nil { + return m.Current + } + return nil +} + +func (m *UpgradeReleaseRequest) GetTarget() *Release { + if m != nil { + return m.Target + } + return nil +} + +type UpgradeReleaseResponse struct { + Release *Release `protobuf:"bytes,1,opt,name=release" json:"release,omitempty"` + Result *Result `protobuf:"bytes,2,opt,name=result" json:"result,omitempty"` +} + +func (m *UpgradeReleaseResponse) Reset() { *m = UpgradeReleaseResponse{} } +func (m *UpgradeReleaseResponse) String() string { return proto.CompactTextString(m) } +func (*UpgradeReleaseResponse) ProtoMessage() {} +func (*UpgradeReleaseResponse) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{8} } + +func (m *UpgradeReleaseResponse) GetRelease() *Release { + if m != nil { + return m.Release + } + return nil +} + +func (m *UpgradeReleaseResponse) GetResult() *Result { + if m != nil { + return m.Result + } + return nil +} + +type RollbackReleaseRequest struct { + Current *Release `protobuf:"bytes,1,opt,name=current" json:"current,omitempty"` + Target *Release `protobuf:"bytes,2,opt,name=target" json:"target,omitempty"` + Timeout int64 `protobuf:"varint,3,opt,name=Timeout" json:"Timeout,omitempty"` + Wait bool `protobuf:"varint,4,opt,name=Wait" json:"Wait,omitempty"` + Recreate bool `protobuf:"varint,5,opt,name=Recreate" json:"Recreate,omitempty"` +} + +func (m *RollbackReleaseRequest) Reset() { *m = RollbackReleaseRequest{} } +func (m *RollbackReleaseRequest) String() string { return proto.CompactTextString(m) } +func (*RollbackReleaseRequest) ProtoMessage() {} +func (*RollbackReleaseRequest) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{9} } + +func (m *RollbackReleaseRequest) GetCurrent() *Release { + if m != nil { + return m.Current + } + return nil +} + +func (m *RollbackReleaseRequest) GetTarget() *Release { + if m != nil { + return m.Target + } + return nil +} + +type RollbackReleaseResponse struct { + Release *Release `protobuf:"bytes,1,opt,name=release" json:"release,omitempty"` + Result *Result `protobuf:"bytes,2,opt,name=result" json:"result,omitempty"` +} + +func (m *RollbackReleaseResponse) Reset() { *m = RollbackReleaseResponse{} } +func (m *RollbackReleaseResponse) String() string { return proto.CompactTextString(m) } +func (*RollbackReleaseResponse) ProtoMessage() {} +func (*RollbackReleaseResponse) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{10} } + +func (m *RollbackReleaseResponse) GetRelease() *Release { + if m != nil { + return m.Release + } + return nil +} + +func (m *RollbackReleaseResponse) GetResult() *Result { + if m != nil { + return m.Result + } + return nil +} + +func init() { + proto.RegisterType((*Result)(nil), "hapi.release.Result") + proto.RegisterType((*VersionReleaseRequest)(nil), "hapi.release.VersionReleaseRequest") + proto.RegisterType((*VersionReleaseResponse)(nil), "hapi.release.VersionReleaseResponse") + proto.RegisterType((*InstallReleaseRequest)(nil), "hapi.release.InstallReleaseRequest") + proto.RegisterType((*InstallReleaseResponse)(nil), "hapi.release.InstallReleaseResponse") + proto.RegisterType((*DeleteReleaseRequest)(nil), "hapi.release.DeleteReleaseRequest") + proto.RegisterType((*DeleteReleaseResponse)(nil), "hapi.release.DeleteReleaseResponse") + proto.RegisterType((*UpgradeReleaseRequest)(nil), "hapi.release.UpgradeReleaseRequest") + proto.RegisterType((*UpgradeReleaseResponse)(nil), "hapi.release.UpgradeReleaseResponse") + proto.RegisterType((*RollbackReleaseRequest)(nil), "hapi.release.RollbackReleaseRequest") + proto.RegisterType((*RollbackReleaseResponse)(nil), "hapi.release.RollbackReleaseResponse") + proto.RegisterEnum("hapi.release.Result_Status", Result_Status_name, Result_Status_value) +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion3 + +// Client API for ReleaseModuleService service + +type ReleaseModuleServiceClient interface { + Version(ctx context.Context, in *VersionReleaseRequest, opts ...grpc.CallOption) (*VersionReleaseResponse, error) + // InstallRelease requests installation of a chart as a new release. + InstallRelease(ctx context.Context, in *InstallReleaseRequest, opts ...grpc.CallOption) (*InstallReleaseResponse, error) + // DeleteRelease requests deletion of a named release. + DeleteRelease(ctx context.Context, in *DeleteReleaseRequest, opts ...grpc.CallOption) (*DeleteReleaseResponse, error) + // RollbackRelease rolls back a release to a previous version. + RollbackRelease(ctx context.Context, in *RollbackReleaseRequest, opts ...grpc.CallOption) (*RollbackReleaseResponse, error) + // UpgradeRelease updates release content. + UpgradeRelease(ctx context.Context, in *UpgradeReleaseRequest, opts ...grpc.CallOption) (*UpgradeReleaseResponse, error) +} + +type releaseModuleServiceClient struct { + cc *grpc.ClientConn +} + +func NewReleaseModuleServiceClient(cc *grpc.ClientConn) ReleaseModuleServiceClient { + return &releaseModuleServiceClient{cc} +} + +func (c *releaseModuleServiceClient) Version(ctx context.Context, in *VersionReleaseRequest, opts ...grpc.CallOption) (*VersionReleaseResponse, error) { + out := new(VersionReleaseResponse) + err := grpc.Invoke(ctx, "/hapi.release.ReleaseModuleService/Version", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *releaseModuleServiceClient) InstallRelease(ctx context.Context, in *InstallReleaseRequest, opts ...grpc.CallOption) (*InstallReleaseResponse, error) { + out := new(InstallReleaseResponse) + err := grpc.Invoke(ctx, "/hapi.release.ReleaseModuleService/InstallRelease", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *releaseModuleServiceClient) DeleteRelease(ctx context.Context, in *DeleteReleaseRequest, opts ...grpc.CallOption) (*DeleteReleaseResponse, error) { + out := new(DeleteReleaseResponse) + err := grpc.Invoke(ctx, "/hapi.release.ReleaseModuleService/DeleteRelease", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *releaseModuleServiceClient) RollbackRelease(ctx context.Context, in *RollbackReleaseRequest, opts ...grpc.CallOption) (*RollbackReleaseResponse, error) { + out := new(RollbackReleaseResponse) + err := grpc.Invoke(ctx, "/hapi.release.ReleaseModuleService/RollbackRelease", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *releaseModuleServiceClient) UpgradeRelease(ctx context.Context, in *UpgradeReleaseRequest, opts ...grpc.CallOption) (*UpgradeReleaseResponse, error) { + out := new(UpgradeReleaseResponse) + err := grpc.Invoke(ctx, "/hapi.release.ReleaseModuleService/UpgradeRelease", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// Server API for ReleaseModuleService service + +type ReleaseModuleServiceServer interface { + Version(context.Context, *VersionReleaseRequest) (*VersionReleaseResponse, error) + // InstallRelease requests installation of a chart as a new release. + InstallRelease(context.Context, *InstallReleaseRequest) (*InstallReleaseResponse, error) + // DeleteRelease requests deletion of a named release. + DeleteRelease(context.Context, *DeleteReleaseRequest) (*DeleteReleaseResponse, error) + // RollbackRelease rolls back a release to a previous version. + RollbackRelease(context.Context, *RollbackReleaseRequest) (*RollbackReleaseResponse, error) + // UpgradeRelease updates release content. + UpgradeRelease(context.Context, *UpgradeReleaseRequest) (*UpgradeReleaseResponse, error) +} + +func RegisterReleaseModuleServiceServer(s *grpc.Server, srv ReleaseModuleServiceServer) { + s.RegisterService(&_ReleaseModuleService_serviceDesc, srv) +} + +func _ReleaseModuleService_Version_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(VersionReleaseRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ReleaseModuleServiceServer).Version(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/hapi.release.ReleaseModuleService/Version", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ReleaseModuleServiceServer).Version(ctx, req.(*VersionReleaseRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ReleaseModuleService_InstallRelease_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(InstallReleaseRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ReleaseModuleServiceServer).InstallRelease(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/hapi.release.ReleaseModuleService/InstallRelease", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ReleaseModuleServiceServer).InstallRelease(ctx, req.(*InstallReleaseRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ReleaseModuleService_DeleteRelease_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteReleaseRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ReleaseModuleServiceServer).DeleteRelease(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/hapi.release.ReleaseModuleService/DeleteRelease", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ReleaseModuleServiceServer).DeleteRelease(ctx, req.(*DeleteReleaseRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ReleaseModuleService_RollbackRelease_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RollbackReleaseRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ReleaseModuleServiceServer).RollbackRelease(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/hapi.release.ReleaseModuleService/RollbackRelease", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ReleaseModuleServiceServer).RollbackRelease(ctx, req.(*RollbackReleaseRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ReleaseModuleService_UpgradeRelease_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UpgradeReleaseRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ReleaseModuleServiceServer).UpgradeRelease(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/hapi.release.ReleaseModuleService/UpgradeRelease", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ReleaseModuleServiceServer).UpgradeRelease(ctx, req.(*UpgradeReleaseRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _ReleaseModuleService_serviceDesc = grpc.ServiceDesc{ + ServiceName: "hapi.release.ReleaseModuleService", + HandlerType: (*ReleaseModuleServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Version", + Handler: _ReleaseModuleService_Version_Handler, + }, + { + MethodName: "InstallRelease", + Handler: _ReleaseModuleService_InstallRelease_Handler, + }, + { + MethodName: "DeleteRelease", + Handler: _ReleaseModuleService_DeleteRelease_Handler, + }, + { + MethodName: "RollbackRelease", + Handler: _ReleaseModuleService_RollbackRelease_Handler, + }, + { + MethodName: "UpgradeRelease", + Handler: _ReleaseModuleService_UpgradeRelease_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: fileDescriptor2, +} + +func init() { proto.RegisterFile("hapi/release/modules.proto", fileDescriptor2) } + +var fileDescriptor2 = []byte{ + // 523 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xd4, 0x55, 0xc1, 0x6e, 0xd3, 0x40, + 0x10, 0x8d, 0xe3, 0x36, 0xa9, 0x27, 0x14, 0xac, 0x55, 0x9c, 0x5a, 0x3e, 0x45, 0x5b, 0x90, 0x72, + 0x80, 0x44, 0x0a, 0x57, 0x2e, 0x90, 0x86, 0x16, 0x21, 0x5c, 0x69, 0x4d, 0x5a, 0xa9, 0x12, 0x12, + 0xdb, 0x74, 0x08, 0x16, 0x1b, 0x3b, 0xac, 0xd7, 0x81, 0xdf, 0x83, 0xcf, 0xe1, 0x2b, 0x90, 0x1d, + 0xbb, 0xaa, 0x17, 0xd3, 0x0a, 0x21, 0x45, 0xea, 0x29, 0x33, 0x9e, 0x97, 0xb7, 0x33, 0xcf, 0xb3, + 0xcf, 0xe0, 0x7d, 0xe6, 0xab, 0x70, 0x24, 0x51, 0x20, 0x4f, 0x70, 0xb4, 0x8c, 0xaf, 0x52, 0x81, + 0xc9, 0x70, 0x25, 0x63, 0x15, 0x93, 0x07, 0x59, 0x6d, 0x58, 0xd4, 0xbc, 0x2a, 0xb2, 0xf8, 0xdd, + 0x20, 0xa9, 0x80, 0x16, 0xc3, 0x24, 0x15, 0x8a, 0x10, 0xd8, 0x09, 0xa3, 0x4f, 0xb1, 0x6b, 0xf4, + 0x8d, 0x81, 0xc5, 0xf2, 0x98, 0xd8, 0x60, 0x8a, 0x78, 0xe1, 0x36, 0xfb, 0xe6, 0xc0, 0x62, 0x59, + 0x48, 0x5f, 0x40, 0x2b, 0x50, 0x5c, 0xa5, 0x09, 0xe9, 0x40, 0x7b, 0xe6, 0xbf, 0xf5, 0x4f, 0xcf, + 0x7d, 0xbb, 0x91, 0x25, 0xc1, 0x6c, 0x32, 0x99, 0x06, 0x81, 0x6d, 0x90, 0x7d, 0xb0, 0x66, 0xfe, + 0xe4, 0xe4, 0xa5, 0x7f, 0x3c, 0x3d, 0xb2, 0x9b, 0xc4, 0x82, 0xdd, 0x29, 0x63, 0xa7, 0xcc, 0x36, + 0xe9, 0x01, 0x38, 0x67, 0x28, 0x93, 0x30, 0x8e, 0xd8, 0xa6, 0x0b, 0x86, 0x5f, 0x53, 0x4c, 0x14, + 0x7d, 0x0d, 0x3d, 0xbd, 0x90, 0xac, 0xe2, 0x28, 0xc1, 0xac, 0xad, 0x88, 0x2f, 0xb1, 0x6c, 0x2b, + 0x8b, 0x89, 0x0b, 0xed, 0xf5, 0x06, 0xed, 0x36, 0xf3, 0xc7, 0x65, 0x4a, 0x4f, 0xc0, 0x79, 0x13, + 0x25, 0x8a, 0x0b, 0x51, 0x3d, 0x80, 0x8c, 0xa0, 0x5d, 0x0c, 0x9e, 0x33, 0x75, 0xc6, 0xce, 0xf0, + 0xa6, 0x46, 0xc3, 0x12, 0x5e, 0xa2, 0xe8, 0x37, 0xe8, 0xe9, 0x4c, 0x45, 0x47, 0xff, 0x4a, 0x45, + 0x9e, 0x42, 0x4b, 0xe6, 0x1a, 0xe7, 0xdd, 0x76, 0xc6, 0x5d, 0x1d, 0x9f, 0xd5, 0x58, 0x81, 0xa1, + 0xc7, 0xd0, 0x3d, 0x42, 0x81, 0x0a, 0xff, 0x77, 0x82, 0x35, 0x38, 0x1a, 0xd1, 0x76, 0x06, 0xf8, + 0x61, 0x80, 0x33, 0x5b, 0x2d, 0x24, 0xbf, 0xaa, 0x19, 0x61, 0x9e, 0x4a, 0x89, 0x91, 0xba, 0xe3, + 0xe0, 0x02, 0x45, 0x9e, 0x41, 0x4b, 0x71, 0xb9, 0xc0, 0xf2, 0xe0, 0xbf, 0xe0, 0x0b, 0x50, 0xb6, + 0x17, 0xef, 0xc3, 0x25, 0xc6, 0xa9, 0x72, 0xcd, 0xbe, 0x31, 0x30, 0x59, 0x99, 0x66, 0x5b, 0x74, + 0xce, 0x43, 0xe5, 0xee, 0xf4, 0x8d, 0xc1, 0x1e, 0xcb, 0x63, 0xe2, 0xc1, 0x1e, 0xc3, 0xb9, 0x44, + 0xae, 0xd0, 0xdd, 0xcd, 0x9f, 0x5f, 0xe7, 0xd9, 0xdb, 0xd7, 0x47, 0xd8, 0x8e, 0x78, 0x3f, 0x0d, + 0xe8, 0xb1, 0x58, 0x88, 0x4b, 0x3e, 0xff, 0x72, 0x6f, 0xd5, 0xfb, 0x0e, 0x07, 0x7f, 0xcc, 0xb0, + 0x15, 0xf9, 0xc6, 0xbf, 0x4c, 0xe8, 0x16, 0x14, 0xef, 0x72, 0x47, 0x0c, 0x50, 0xae, 0xc3, 0x39, + 0x92, 0x33, 0x68, 0x17, 0x06, 0x43, 0x0e, 0xab, 0x0c, 0xb5, 0x86, 0xe4, 0x3d, 0xbe, 0x1d, 0xb4, + 0x99, 0x86, 0x36, 0xc8, 0x07, 0x78, 0x58, 0xb5, 0x09, 0x9d, 0xbe, 0xd6, 0x8e, 0x74, 0xfa, 0x7a, + 0xa7, 0xa1, 0x0d, 0x72, 0x01, 0xfb, 0x95, 0x3b, 0x4c, 0x68, 0xf5, 0x8f, 0x75, 0x4e, 0xe1, 0x1d, + 0xde, 0x8a, 0xb9, 0xe6, 0xfe, 0x08, 0x8f, 0xb4, 0xb7, 0x44, 0xb4, 0xb6, 0xea, 0x17, 0xd1, 0x7b, + 0x72, 0x07, 0xea, 0xa6, 0x38, 0xd5, 0x5b, 0xa4, 0x8b, 0x53, 0x6b, 0x13, 0xba, 0x38, 0xf5, 0x17, + 0x91, 0x36, 0x5e, 0x59, 0x17, 0xe5, 0x96, 0x5c, 0xb6, 0xf2, 0xaf, 0xd9, 0xf3, 0xdf, 0x01, 0x00, + 0x00, 0xff, 0xff, 0x6c, 0xb6, 0x1e, 0x06, 0x15, 0x07, 0x00, 0x00, +} diff --git a/pkg/proto/hapi/release/release.pb.go b/pkg/proto/hapi/release/release.pb.go index 72255e3e2..ce43ec7ef 100644 --- a/pkg/proto/hapi/release/release.pb.go +++ b/pkg/proto/hapi/release/release.pb.go @@ -40,7 +40,7 @@ type Release struct { func (m *Release) Reset() { *m = Release{} } func (m *Release) String() string { return proto.CompactTextString(m) } func (*Release) ProtoMessage() {} -func (*Release) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{0} } +func (*Release) Descriptor() ([]byte, []int) { return fileDescriptor3, []int{0} } func (m *Release) GetInfo() *Info { if m != nil { @@ -74,9 +74,9 @@ func init() { proto.RegisterType((*Release)(nil), "hapi.release.Release") } -func init() { proto.RegisterFile("hapi/release/release.proto", fileDescriptor2) } +func init() { proto.RegisterFile("hapi/release/release.proto", fileDescriptor3) } -var fileDescriptor2 = []byte{ +var fileDescriptor3 = []byte{ // 256 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x64, 0x90, 0xbf, 0x4e, 0xc3, 0x40, 0x0c, 0xc6, 0x95, 0x36, 0x7f, 0x1a, 0xc3, 0x82, 0x07, 0xb0, 0x22, 0x86, 0x88, 0x01, 0x22, 0x86, diff --git a/pkg/proto/hapi/release/status.pb.go b/pkg/proto/hapi/release/status.pb.go index 29144b7ca..7c7f0f2ea 100644 --- a/pkg/proto/hapi/release/status.pb.go +++ b/pkg/proto/hapi/release/status.pb.go @@ -51,7 +51,7 @@ var Status_Code_value = map[string]int32{ func (x Status_Code) String() string { return proto.EnumName(Status_Code_name, int32(x)) } -func (Status_Code) EnumDescriptor() ([]byte, []int) { return fileDescriptor3, []int{0, 0} } +func (Status_Code) EnumDescriptor() ([]byte, []int) { return fileDescriptor4, []int{0, 0} } // Status defines the status of a release. type Status struct { @@ -67,7 +67,7 @@ type Status struct { func (m *Status) Reset() { *m = Status{} } func (m *Status) String() string { return proto.CompactTextString(m) } func (*Status) ProtoMessage() {} -func (*Status) Descriptor() ([]byte, []int) { return fileDescriptor3, []int{0} } +func (*Status) Descriptor() ([]byte, []int) { return fileDescriptor4, []int{0} } func (m *Status) GetLastTestSuiteRun() *TestSuite { if m != nil { @@ -81,9 +81,9 @@ func init() { proto.RegisterEnum("hapi.release.Status_Code", Status_Code_name, Status_Code_value) } -func init() { proto.RegisterFile("hapi/release/status.proto", fileDescriptor3) } +func init() { proto.RegisterFile("hapi/release/status.proto", fileDescriptor4) } -var fileDescriptor3 = []byte{ +var fileDescriptor4 = []byte{ // 291 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x54, 0x90, 0xdf, 0x6a, 0xc2, 0x30, 0x14, 0xc6, 0x57, 0xad, 0x3a, 0x8f, 0x22, 0x21, 0x1b, 0xac, 0xca, 0x06, 0xc5, 0xab, 0xde, 0xac, diff --git a/pkg/proto/hapi/release/test_run.pb.go b/pkg/proto/hapi/release/test_run.pb.go index 51b3e72f9..1de75fb77 100644 --- a/pkg/proto/hapi/release/test_run.pb.go +++ b/pkg/proto/hapi/release/test_run.pb.go @@ -36,7 +36,7 @@ var TestRun_Status_value = map[string]int32{ func (x TestRun_Status) String() string { return proto.EnumName(TestRun_Status_name, int32(x)) } -func (TestRun_Status) EnumDescriptor() ([]byte, []int) { return fileDescriptor4, []int{0, 0} } +func (TestRun_Status) EnumDescriptor() ([]byte, []int) { return fileDescriptor5, []int{0, 0} } type TestRun struct { Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` @@ -49,7 +49,7 @@ type TestRun struct { func (m *TestRun) Reset() { *m = TestRun{} } func (m *TestRun) String() string { return proto.CompactTextString(m) } func (*TestRun) ProtoMessage() {} -func (*TestRun) Descriptor() ([]byte, []int) { return fileDescriptor4, []int{0} } +func (*TestRun) Descriptor() ([]byte, []int) { return fileDescriptor5, []int{0} } func (m *TestRun) GetStartedAt() *google_protobuf.Timestamp { if m != nil { @@ -70,9 +70,9 @@ func init() { proto.RegisterEnum("hapi.release.TestRun_Status", TestRun_Status_name, TestRun_Status_value) } -func init() { proto.RegisterFile("hapi/release/test_run.proto", fileDescriptor4) } +func init() { proto.RegisterFile("hapi/release/test_run.proto", fileDescriptor5) } -var fileDescriptor4 = []byte{ +var fileDescriptor5 = []byte{ // 265 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x84, 0x8f, 0x41, 0x4b, 0xfb, 0x40, 0x14, 0xc4, 0xff, 0xc9, 0xbf, 0x26, 0x64, 0x53, 0x24, 0xec, 0x29, 0x54, 0xc1, 0xd0, 0x53, 0x4e, diff --git a/pkg/proto/hapi/release/test_suite.pb.go b/pkg/proto/hapi/release/test_suite.pb.go index 27fe45ac5..a7e7cde17 100644 --- a/pkg/proto/hapi/release/test_suite.pb.go +++ b/pkg/proto/hapi/release/test_suite.pb.go @@ -27,7 +27,7 @@ type TestSuite struct { func (m *TestSuite) Reset() { *m = TestSuite{} } func (m *TestSuite) String() string { return proto.CompactTextString(m) } func (*TestSuite) ProtoMessage() {} -func (*TestSuite) Descriptor() ([]byte, []int) { return fileDescriptor5, []int{0} } +func (*TestSuite) Descriptor() ([]byte, []int) { return fileDescriptor6, []int{0} } func (m *TestSuite) GetStartedAt() *google_protobuf.Timestamp { if m != nil { @@ -54,9 +54,9 @@ func init() { proto.RegisterType((*TestSuite)(nil), "hapi.release.TestSuite") } -func init() { proto.RegisterFile("hapi/release/test_suite.proto", fileDescriptor5) } +func init() { proto.RegisterFile("hapi/release/test_suite.proto", fileDescriptor6) } -var fileDescriptor5 = []byte{ +var fileDescriptor6 = []byte{ // 207 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x84, 0x8f, 0xc1, 0x4a, 0x86, 0x40, 0x14, 0x85, 0x31, 0x21, 0x71, 0x74, 0x35, 0x10, 0x88, 0x11, 0x49, 0x2b, 0x57, 0x33, 0x60, 0xab, diff --git a/pkg/releaseutil/manifest.go b/pkg/releaseutil/manifest.go index b6bb87b0a..9fb17b5da 100644 --- a/pkg/releaseutil/manifest.go +++ b/pkg/releaseutil/manifest.go @@ -19,6 +19,8 @@ package releaseutil import ( "fmt" "strings" + + "github.com/ghodss/yaml" ) // SimpleHead defines what the structure of the head of a manifest file @@ -38,11 +40,39 @@ func SplitManifests(bigfile string) map[string]string { // array of YAML docs. In the current implementation, the file name is just // a place holder, and doesn't have any further meaning. sep := "\n---\n" + cutset := " \n\t" tpl := "manifest-%d" res := map[string]string{} tmp := strings.Split(bigfile, sep) for i, d := range tmp { - res[fmt.Sprintf(tpl, i)] = d + if len(strings.Trim(d, cutset)) > 0 { + res[fmt.Sprintf(tpl, i)] = d + } } return res } + +// Manifest reperestens a single manifest content with SimpleHead added for additional metadata +type Manifest struct { + SimpleHead + Content string +} + +// SplitManifestsWithHeads +func SplitManifestsWithHeads(bigfile string) ([]Manifest, error) { + raws := SplitManifests(bigfile) + + result := make([]Manifest, 0, len(raws)) + var err error + + for _, raw := range raws { + var head SimpleHead + err = yaml.Unmarshal([]byte(raw), &head) + + result = append(result, Manifest{ + Content: raw, + SimpleHead: head, + }) + } + return result, err +} diff --git a/pkg/releaseutil/manifest_test.go b/pkg/releaseutil/manifest_test.go new file mode 100644 index 000000000..0bcc8e269 --- /dev/null +++ b/pkg/releaseutil/manifest_test.go @@ -0,0 +1,63 @@ +/* +Copyright 2017 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 releaseutil + +import ( + "testing" +) + +func TestSplitManifestsWithHeads(t *testing.T) { + rawManifest := `kind: TestKind +apiVersion: v1 +metadata: + name: TestName + annotations: + key1: value1 + key2: value2` + + rawManifests := rawManifest + "\n---\n" + rawManifest + + manifests, err := SplitManifestsWithHeads(rawManifests) + if err != nil { + t.Errorf("Expected error to be nil, got %s", err) + } + + if len(manifests) != 2 { + t.Errorf("Expected manifests length to be 2, got %d", len(manifests)) + } + + for _, m := range manifests { + if m.SimpleHead.Kind != "TestKind" { + t.Errorf("Expected Kind to be TestKind, got %s", m.SimpleHead.Kind) + } + if m.SimpleHead.Version != "v1" { + t.Errorf("Expected Version to be v1, got %s", m.SimpleHead.Version) + } + if m.SimpleHead.Metadata.Name != "TestName" { + t.Errorf("Expected Name to be TestName, got %s", m.SimpleHead.Metadata.Name) + } + if val1, ok := m.SimpleHead.Metadata.Annotations["key1"]; !ok || val1 != "value1" { + t.Errorf("Expected annotation key1 to be value1, got %s", val1) + } + if val2, ok := m.SimpleHead.Metadata.Annotations["key2"]; !ok || val2 != "value2" { + t.Errorf("Expected annotation key2 to be value2, got %s", val2) + } + if m.Content != rawManifest { + t.Errorf("Expected Content to be equal to original, got %s", m.Content) + } + } +} diff --git a/pkg/rudder/client.go b/pkg/rudder/client.go new file mode 100644 index 000000000..694095ef8 --- /dev/null +++ b/pkg/rudder/client.go @@ -0,0 +1,68 @@ +/* +Copyright 2017 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 rudder // import "k8s.io/helm/pkg/rudder" + +import ( + "fmt" + + "golang.org/x/net/context" + "google.golang.org/grpc" + + "k8s.io/helm/pkg/proto/hapi/release" +) + +// GrpcPort specifies port on which rudder will spawn a server +const ( + GrpcPort = 10001 +) + +var grpcAddr = fmt.Sprintf("127.0.0.1:%d", GrpcPort) + +// InstallRelease calls Rudder InstallRelease method which should create provided release +func InstallRelease(rel *release.InstallReleaseRequest) (*release.InstallReleaseResponse, error) { + //TODO(mkwiek): parametrize this + conn, err := grpc.Dial(grpcAddr, grpc.WithInsecure()) + if err != nil { + return nil, err + } + + defer conn.Close() + client := release.NewReleaseModuleServiceClient(conn) + return client.InstallRelease(context.Background(), rel) +} + +// UpgradeRelease calls Rudder UpgradeRelease method which should perform update +func UpgradeRelease(req *release.UpgradeReleaseRequest) (*release.UpgradeReleaseResponse, error) { + conn, err := grpc.Dial(grpcAddr, grpc.WithInsecure()) + if err != nil { + return nil, err + } + defer conn.Close() + client := release.NewReleaseModuleServiceClient(conn) + return client.UpgradeRelease(context.Background(), req) +} + +// RollbackRelease calls Rudder RollbackRelease method which should perform update +func RollbackRelease(req *release.RollbackReleaseRequest) (*release.RollbackReleaseResponse, error) { + conn, err := grpc.Dial(grpcAddr, grpc.WithInsecure()) + if err != nil { + return nil, err + } + defer conn.Close() + client := release.NewReleaseModuleServiceClient(conn) + return client.RollbackRelease(context.Background(), req) +} diff --git a/pkg/tiller/release_modules.go b/pkg/tiller/release_modules.go new file mode 100644 index 000000000..755e7a66f --- /dev/null +++ b/pkg/tiller/release_modules.go @@ -0,0 +1,90 @@ +/* +Copyright 2017 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 tiller + +import ( + "bytes" + + "k8s.io/helm/pkg/proto/hapi/release" + "k8s.io/helm/pkg/proto/hapi/services" + "k8s.io/helm/pkg/rudder" + "k8s.io/helm/pkg/tiller/environment" +) + +// ReleaseModule is an interface that allows ReleaseServer to run operations on release via either local implementation or Rudder service +type ReleaseModule interface { + Create(r *release.Release, req *services.InstallReleaseRequest, env *environment.Environment) error + Update(current, target *release.Release, req *services.UpdateReleaseRequest, env *environment.Environment) error + Rollback(current, target *release.Release, req *services.RollbackReleaseRequest, env *environment.Environment) error +} + +// LocalReleaseModule is a local implementation of ReleaseModule +type LocalReleaseModule struct{} + +// Create creates a release via kubeclient from provided environment +func (m *LocalReleaseModule) Create(r *release.Release, req *services.InstallReleaseRequest, env *environment.Environment) error { + b := bytes.NewBufferString(r.Manifest) + return env.KubeClient.Create(r.Namespace, b, req.Timeout, req.Wait) +} + +func (m *LocalReleaseModule) Update(current, target *release.Release, req *services.UpdateReleaseRequest, env *environment.Environment) error { + c := bytes.NewBufferString(current.Manifest) + t := bytes.NewBufferString(target.Manifest) + return env.KubeClient.Update(target.Namespace, c, t, req.Recreate, req.Timeout, req.Wait) +} + +func (m *LocalReleaseModule) Rollback(current, target *release.Release, req *services.RollbackReleaseRequest, env *environment.Environment) error { + c := bytes.NewBufferString(current.Manifest) + t := bytes.NewBufferString(target.Manifest) + return env.KubeClient.Update(target.Namespace, c, t, req.Recreate, req.Timeout, req.Wait) +} + +// RemoteReleaseModule is a ReleaseModule which calls Rudder service to operate on a release +type RemoteReleaseModule struct{} + +// Create calls rudder.InstallRelease +func (m *RemoteReleaseModule) Create(r *release.Release, req *services.InstallReleaseRequest, env *environment.Environment) error { + request := &release.InstallReleaseRequest{Release: r} + _, err := rudder.InstallRelease(request) + return err +} + +// Update calls rudder.UpgradeRelease +func (m *RemoteReleaseModule) Update(current, target *release.Release, req *services.UpdateReleaseRequest, env *environment.Environment) error { + upgrade := &release.UpgradeReleaseRequest{ + Current: current, + Target: target, + Recreate: req.Recreate, + Timeout: req.Timeout, + Wait: req.Wait, + } + _, err := rudder.UpgradeRelease(upgrade) + return err +} + +// Rollback calls rudder.Rollback +func (m *RemoteReleaseModule) Rollback(current, target *release.Release, req *services.RollbackReleaseRequest, env *environment.Environment) error { + rollback := &release.RollbackReleaseRequest{ + Current: current, + Target: target, + Recreate: req.Recreate, + Timeout: req.Timeout, + Wait: req.Wait, + } + _, err := rudder.RollbackRelease(rollback) + return err +} diff --git a/pkg/tiller/release_server.go b/pkg/tiller/release_server.go index 873d2335a..e333a6af1 100644 --- a/pkg/tiller/release_server.go +++ b/pkg/tiller/release_server.go @@ -83,15 +83,24 @@ var ValidName = regexp.MustCompile("^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])+ // ReleaseServer implements the server-side gRPC endpoint for the HAPI services. type ReleaseServer struct { + ReleaseModule env *environment.Environment clientset internalclientset.Interface } // NewReleaseServer creates a new release server. -func NewReleaseServer(env *environment.Environment, clientset internalclientset.Interface) *ReleaseServer { +func NewReleaseServer(env *environment.Environment, clientset internalclientset.Interface, useRemote bool) *ReleaseServer { + var releaseModule ReleaseModule + if useRemote { + releaseModule = &RemoteReleaseModule{} + } else { + releaseModule = &LocalReleaseModule{} + } + return &ReleaseServer{ - env: env, - clientset: clientset, + env: env, + clientset: clientset, + ReleaseModule: releaseModule, } } @@ -318,8 +327,7 @@ func (s *ReleaseServer) performUpdate(originalRelease, updatedRelease *release.R return res, err } } - - if err := s.performKubeUpdate(originalRelease, updatedRelease, req.Recreate, req.Timeout, req.Wait); err != nil { + if err := s.ReleaseModule.Update(originalRelease, updatedRelease, req, s.env); err != nil { msg := fmt.Sprintf("Upgrade %q failed: %s", updatedRelease.Name, err) log.Printf("warning: %s", msg) originalRelease.Info.Status.Code = release.Status_SUPERSEDED @@ -477,7 +485,7 @@ func (s *ReleaseServer) performRollback(currentRelease, targetRelease *release.R } } - if err := s.performKubeUpdate(currentRelease, targetRelease, req.Recreate, req.Timeout, req.Wait); err != nil { + if err := s.ReleaseModule.Rollback(currentRelease, targetRelease, req, s.env); err != nil { msg := fmt.Sprintf("Rollback %q failed: %s", targetRelease.Name, err) log.Printf("warning: %s", msg) currentRelease.Info.Status.Code = release.Status_SUPERSEDED @@ -503,13 +511,6 @@ func (s *ReleaseServer) performRollback(currentRelease, targetRelease *release.R return res, nil } -func (s *ReleaseServer) performKubeUpdate(currentRelease, targetRelease *release.Release, recreate bool, timeout int64, shouldWait bool) error { - kubeCli := s.env.KubeClient - current := bytes.NewBufferString(currentRelease.Manifest) - target := bytes.NewBufferString(targetRelease.Manifest) - return kubeCli.Update(targetRelease.Namespace, current, target, recreate, timeout, shouldWait) -} - // prepareRollback finds the previous release and prepares a new release object with // the previous release's configuration func (s *ReleaseServer) prepareRollback(req *services.RollbackReleaseRequest) (*release.Release, *release.Release, error) { @@ -851,8 +852,12 @@ func (s *ReleaseServer) performRelease(r *release.Release, req *services.Install // update new release with next revision number // so as to append to the old release's history r.Version = old.Version + 1 - - if err := s.performKubeUpdate(old, r, false, req.Timeout, req.Wait); err != nil { + updateReq := &services.UpdateReleaseRequest{ + Wait: req.Wait, + Recreate: false, + Timeout: req.Timeout, + } + if err := s.ReleaseModule.Update(old, r, updateReq, s.env); err != nil { msg := fmt.Sprintf("Release replace %q failed: %s", r.Name, err) log.Printf("warning: %s", msg) old.Info.Status.Code = release.Status_SUPERSEDED @@ -866,8 +871,7 @@ func (s *ReleaseServer) performRelease(r *release.Release, req *services.Install default: // nothing to replace, create as normal // regular manifests - b := bytes.NewBufferString(r.Manifest) - if err := s.env.KubeClient.Create(r.Namespace, b, req.Timeout, req.Wait); err != nil { + if err := s.ReleaseModule.Create(r, req, s.env); err != nil { msg := fmt.Sprintf("Release %q failed: %s", r.Name, err) log.Printf("warning: %s", msg) r.Info.Status.Code = release.Status_FAILED diff --git a/pkg/tiller/release_server_test.go b/pkg/tiller/release_server_test.go index 185ef05e7..5ffc8a71c 100644 --- a/pkg/tiller/release_server_test.go +++ b/pkg/tiller/release_server_test.go @@ -98,8 +98,9 @@ data: func rsFixture() *ReleaseServer { return &ReleaseServer{ - env: MockEnvironment(), - clientset: fake.NewSimpleClientset(), + ReleaseModule: &LocalReleaseModule{}, + env: MockEnvironment(), + clientset: fake.NewSimpleClientset(), } } diff --git a/rootfs/Dockerfile.experimental b/rootfs/Dockerfile.experimental new file mode 100644 index 000000000..0528471e6 --- /dev/null +++ b/rootfs/Dockerfile.experimental @@ -0,0 +1,24 @@ +# Copyright 2017 The Kubernetes Authors. +# +# 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. + +FROM alpine:3.3 + +ENV HOME /tmp + +COPY . / + +EXPOSE 44134 + +CMD ["/tiller", "--experimental-release"] + diff --git a/rootfs/Dockerfile.rudder b/rootfs/Dockerfile.rudder new file mode 100644 index 000000000..d39d0ebdb --- /dev/null +++ b/rootfs/Dockerfile.rudder @@ -0,0 +1,23 @@ +# Copyright 2017 The Kubernetes Authors. +# +# 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. + +FROM alpine:3.3 + +ENV HOME /tmp + +COPY . / + +EXPOSE 10001 + +CMD ["/rudder"] diff --git a/versioning.mk b/versioning.mk index b336a7999..54986a7f9 100644 --- a/versioning.mk +++ b/versioning.mk @@ -14,7 +14,9 @@ DOCKER_VERSION ?= git-${GIT_SHA} BINARY_VERSION ?= ${GIT_TAG}-${GIT_SHA} IMAGE := ${DOCKER_REGISTRY}/${IMAGE_PREFIX}/${SHORT_NAME}:${DOCKER_VERSION} +IMAGE_RUDDER := ${DOCKER_REGISTRY}/${IMAGE_PREFIX}/${SHORT_NAME_RUDDER}:${DOCKER_VERSION} MUTABLE_IMAGE := ${DOCKER_REGISTRY}/${IMAGE_PREFIX}/${SHORT_NAME}:${MUTABLE_VERSION} +MUTABLE_IMAGE_RUDDER:= ${DOCKER_REGISTRY}/${IMAGE_PREFIX}/${SHORT_NAME_RUDDER}:${DOCKER_VERSION} LDFLAGS += -X k8s.io/helm/pkg/version.Version=${GIT_TAG} LDFLAGS += -X k8s.io/helm/pkg/version.GitCommit=${GIT_COMMIT}