mirror of https://github.com/helm/helm
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
674 lines
20 KiB
674 lines
20 KiB
/*
|
|
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 helm // import "k8s.io/helm/pkg/helm"
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"fmt"
|
|
"github.com/golang/protobuf/ptypes"
|
|
"github.com/technosophos/moniker"
|
|
"golang.org/x/net/context"
|
|
"google.golang.org/grpc"
|
|
"gopkg.in/square/go-jose.v1/json"
|
|
hapi "k8s.io/helm/api"
|
|
cs "k8s.io/helm/client/clientset"
|
|
"k8s.io/helm/pkg/chartutil"
|
|
"k8s.io/helm/pkg/kube"
|
|
hapi_chart "k8s.io/helm/pkg/proto/hapi/chart"
|
|
rs "k8s.io/helm/pkg/proto/hapi/release"
|
|
rls "k8s.io/helm/pkg/proto/hapi/services"
|
|
"k8s.io/kubernetes/pkg/api"
|
|
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
|
"k8s.io/kubernetes/pkg/client/restclient"
|
|
rest "k8s.io/kubernetes/pkg/client/restclient"
|
|
"k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
|
|
"log"
|
|
"math/rand"
|
|
"strconv"
|
|
"time"
|
|
)
|
|
|
|
// Client manages client side of the helm-tiller protocol
|
|
func init() {
|
|
rand.Seed(time.Now().UnixNano())
|
|
}
|
|
|
|
type Client struct {
|
|
opts options
|
|
}
|
|
|
|
type ExtensionsClient struct {
|
|
restClient rest.Interface
|
|
}
|
|
|
|
// NewClient creates a new client.
|
|
func NewClient(opts ...Option) *Client {
|
|
var c Client
|
|
return c.Option(opts...)
|
|
}
|
|
|
|
// Option configures the helm client with the provided options
|
|
func (h *Client) Option(opts ...Option) *Client {
|
|
for _, opt := range opts {
|
|
opt(&h.opts)
|
|
}
|
|
return h
|
|
}
|
|
|
|
// ListReleases lists the current releases.
|
|
func (h *Client) ListReleases(opts ...ReleaseListOption) (*rls.ListReleasesResponse, error) {
|
|
for _, opt := range opts {
|
|
opt(&h.opts)
|
|
}
|
|
req := &h.opts.listReq
|
|
ctx := NewContext()
|
|
|
|
if h.opts.before != nil {
|
|
if err := h.opts.before(ctx, req); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
return h.list(ctx, req)
|
|
}
|
|
|
|
// InstallRelease loads a chart from chstr, installs it and returns the release response.
|
|
func (h *Client) InstallRelease(chstr, ns string, opts ...InstallOption) (*rls.InstallReleaseResponse, error) {
|
|
// load the chart to install
|
|
chart, err := chartutil.Load(chstr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return h.InstallReleaseFromChart(chart, ns, opts...)
|
|
}
|
|
|
|
// InstallReleaseFromChart installs a new chart and returns the release response.
|
|
func (h *Client) InstallReleaseFromChart(chart *hapi_chart.Chart, ns string, opts ...InstallOption) (*rls.InstallReleaseResponse, error) {
|
|
// apply the install options
|
|
for _, opt := range opts {
|
|
opt(&h.opts)
|
|
}
|
|
req := &h.opts.instReq
|
|
req.Chart = chart
|
|
req.Namespace = ns
|
|
req.DryRun = h.opts.dryRun
|
|
req.DisableHooks = h.opts.disableHooks
|
|
req.ReuseName = h.opts.reuseName
|
|
ctx := NewContext()
|
|
|
|
if h.opts.before != nil {
|
|
if err := h.opts.before(ctx, req); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
return h.install(ctx, req)
|
|
}
|
|
|
|
// DeleteRelease uninstalls a named release and returns the response.
|
|
func (h *Client) DeleteRelease(rlsName string, namespace string, opts ...DeleteOption) (*rls.UninstallReleaseResponse, error) {
|
|
// apply the uninstall options
|
|
for _, opt := range opts {
|
|
opt(&h.opts)
|
|
}
|
|
|
|
if h.opts.dryRun {
|
|
// In the dry run case, just see if the release exists
|
|
r, err := h.ReleaseContent(rlsName)
|
|
if err != nil {
|
|
return &rls.UninstallReleaseResponse{}, err
|
|
}
|
|
return &rls.UninstallReleaseResponse{Release: r.Release}, nil
|
|
}
|
|
|
|
req := &h.opts.uninstallReq
|
|
req.Name = rlsName
|
|
req.DisableHooks = h.opts.disableHooks
|
|
ctx := NewContext()
|
|
|
|
if h.opts.before != nil {
|
|
if err := h.opts.before(ctx, req); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
return h.delete(ctx, namespace, req)
|
|
}
|
|
|
|
// UpdateRelease updates a release to a new/different chart
|
|
func (h *Client) UpdateRelease(rlsName string, chstr string, namespace string, opts ...UpdateOption) (*rls.UpdateReleaseResponse, error) {
|
|
// load the chart to update
|
|
chart, err := chartutil.Load(chstr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return h.UpdateReleaseFromChart(rlsName, chart, namespace, opts...)
|
|
}
|
|
|
|
// UpdateReleaseFromChart updates a release to a new/different chart
|
|
func (h *Client) UpdateReleaseFromChart(rlsName string, chart *hapi_chart.Chart, namespace string, opts ...UpdateOption) (*rls.UpdateReleaseResponse, error) {
|
|
|
|
// apply the update options
|
|
for _, opt := range opts {
|
|
opt(&h.opts)
|
|
}
|
|
req := &h.opts.updateReq
|
|
req.Chart = chart
|
|
req.DryRun = h.opts.dryRun
|
|
req.Name = rlsName
|
|
req.DisableHooks = h.opts.disableHooks
|
|
req.Recreate = h.opts.recreate
|
|
req.ResetValues = h.opts.resetValues
|
|
ctx := NewContext()
|
|
if h.opts.before != nil {
|
|
if err := h.opts.before(ctx, req); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
return h.update(ctx, namespace, req)
|
|
}
|
|
|
|
// GetVersion returns the server version
|
|
func (h *Client) GetVersion(opts ...VersionOption) (*rls.GetVersionResponse, error) {
|
|
for _, opt := range opts {
|
|
opt(&h.opts)
|
|
}
|
|
req := &rls.GetVersionRequest{}
|
|
ctx := NewContext()
|
|
|
|
if h.opts.before != nil {
|
|
if err := h.opts.before(ctx, req); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
return h.version(ctx, req)
|
|
}
|
|
|
|
// RollbackRelease rolls back a release to the previous version
|
|
func (h *Client) RollbackRelease(rlsName string, namespace string, opts ...RollbackOption) (*rls.RollbackReleaseResponse, error) {
|
|
for _, opt := range opts {
|
|
opt(&h.opts)
|
|
}
|
|
req := &h.opts.rollbackReq
|
|
req.DisableHooks = h.opts.disableHooks
|
|
req.DryRun = h.opts.dryRun
|
|
req.Name = rlsName
|
|
ctx := NewContext()
|
|
|
|
if h.opts.before != nil {
|
|
if err := h.opts.before(ctx, req); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
return h.rollback(ctx, namespace, req)
|
|
}
|
|
|
|
// ReleaseStatus returns the given release's status.
|
|
func (h *Client) ReleaseStatus(rlsName string, namespace string, opts ...StatusOption) (*rls.GetReleaseStatusResponse, error) {
|
|
for _, opt := range opts {
|
|
opt(&h.opts)
|
|
}
|
|
req := &h.opts.statusReq
|
|
req.Name = rlsName
|
|
req.Version = h.opts.statusReq.Version
|
|
ctx := NewContext()
|
|
if h.opts.before != nil {
|
|
if err := h.opts.before(ctx, req); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
return h.status(ctx, namespace, req)
|
|
}
|
|
|
|
// ReleaseContent returns the configuration for a given release.
|
|
func (h *Client) ReleaseContent(rlsName string, opts ...ContentOption) (*rls.GetReleaseContentResponse, error) {
|
|
for _, opt := range opts {
|
|
opt(&h.opts)
|
|
}
|
|
req := &h.opts.contentReq
|
|
req.Name = rlsName
|
|
ctx := NewContext()
|
|
if h.opts.before != nil {
|
|
if err := h.opts.before(ctx, req); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
return h.content(ctx, req)
|
|
}
|
|
|
|
// ReleaseHistory returns a release's revision history.
|
|
func (h *Client) ReleaseHistory(rlsName string, opts ...HistoryOption) (*rls.GetHistoryResponse, error) {
|
|
for _, opt := range opts {
|
|
opt(&h.opts)
|
|
}
|
|
|
|
req := &h.opts.histReq
|
|
req.Name = rlsName
|
|
ctx := NewContext()
|
|
|
|
if h.opts.before != nil {
|
|
if err := h.opts.before(ctx, req); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
return h.history(ctx, req)
|
|
}
|
|
|
|
// Executes tiller.ListReleases RPC.
|
|
func (h *Client) list(ctx context.Context, req *rls.ListReleasesRequest) (*rls.ListReleasesResponse, error) {
|
|
c, err := grpc.Dial(h.opts.host, grpc.WithInsecure())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer c.Close()
|
|
|
|
rlc := rls.NewReleaseServiceClient(c)
|
|
s, err := rlc.ListReleases(ctx, req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return s.Recv()
|
|
}
|
|
|
|
// Executes tiller.InstallRelease RPC.
|
|
func (h *Client) install(ctx context.Context, req *rls.InstallReleaseRequest) (*rls.InstallReleaseResponse, error) {
|
|
/* c, err := grpc.Dial(h.opts.host, grpc.WithInsecure())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer c.Close()
|
|
rlc := rls.NewReleaseServiceClient(c)
|
|
return rlc.InstallRelease(ctx, req)*/
|
|
resp := &rls.InstallReleaseResponse{}
|
|
maxTries := 5
|
|
releaseNameMaxLen := 53
|
|
name := req.Name
|
|
client, err := getRESTClient()
|
|
if err != nil {
|
|
return resp, err
|
|
}
|
|
// make uniq name
|
|
if len(name) == 0 {
|
|
for i := 0; i < maxTries; i++ {
|
|
namer := moniker.New()
|
|
name = namer.NameSep("-")
|
|
if len(name) > releaseNameMaxLen {
|
|
name = name[:releaseNameMaxLen]
|
|
}
|
|
rv := name + "-v1"
|
|
err = client.RESTClient().Get().Namespace(req.Namespace).Resource("releaseversion").Name(rv).Do().Error()
|
|
if err == nil {
|
|
fmt.Println("info: Name %q is taken. Searching again.", name)
|
|
} else {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
req.Name = name
|
|
releaseObj := makeReleaseObject(req)
|
|
releaseObj.Spec.Version = 1
|
|
release := new(hapi.Release)
|
|
err = client.RESTClient().Post().Namespace(req.Namespace).Resource("releases").Body(releaseObj).Do().Into(release)
|
|
if err != nil {
|
|
return resp, err
|
|
}
|
|
resp.Release = new(rs.Release)
|
|
resp.Release.Name = release.Name
|
|
resp.Release.Namespace = release.Namespace
|
|
resp.Release.Hooks = release.Spec.Hooks
|
|
resp.Release.Config = release.Spec.Config
|
|
resp.Release.Chart = new(hapi_chart.Chart)
|
|
resp.Release.Chart = release.Spec.Chart.Inline
|
|
resp.Release.Manifest = release.Spec.Manifest
|
|
resp.Release.Info = new(rs.Info)
|
|
resp.Release.Info.Status = new(rs.Status)
|
|
resp.Release.Info.Status.Notes = release.Status.Notes
|
|
resp.Release.Info.Status.Code = release.Status.Code
|
|
resp.Release.Info.Status.Details = release.Status.Details
|
|
firstDeployed, err := ptypes.TimestampProto(release.Status.FirstDeployed.Time)
|
|
if err != nil {
|
|
return resp, err
|
|
}
|
|
resp.Release.Info.FirstDeployed = firstDeployed
|
|
lastDeployed, err := ptypes.TimestampProto(release.Status.LastDeployed.Time)
|
|
if err != nil {
|
|
return resp, err
|
|
}
|
|
resp.Release.Info.FirstDeployed = lastDeployed
|
|
return resp, nil
|
|
}
|
|
|
|
// Executes tiller.UninstallRelease RPC.
|
|
func (h *Client) delete(ctx context.Context, namespace string, req *rls.UninstallReleaseRequest) (*rls.UninstallReleaseResponse, error) {
|
|
/* c, err := grpc.Dial(h.opts.host, grpc.WithInsecure())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer c.Close()
|
|
|
|
rlc := rls.NewReleaseServiceClient(c)
|
|
return rlc.UninstallRelease(ctx, req)*/
|
|
resp := &rls.UninstallReleaseResponse{}
|
|
client, err := getRESTClient()
|
|
// TODO handle response
|
|
//release := new(hapi.Release)
|
|
err = client.RESTClient().Delete().Namespace(namespace).Resource("releases").Name(req.Name).Do().Error()
|
|
if err != nil {
|
|
return resp, err
|
|
}
|
|
return resp, nil
|
|
}
|
|
|
|
// Executes tiller.UpdateRelease RPC.
|
|
func (h *Client) update(ctx context.Context, namespace string, req *rls.UpdateReleaseRequest) (*rls.UpdateReleaseResponse, error) {
|
|
/* c, err := grpc.Dial(h.opts.host, grpc.WithInsecure())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer c.Close()
|
|
|
|
rlc := rls.NewReleaseServiceClient(c)
|
|
return rlc.UpdateRelease(ctx, req)*/
|
|
resp := &rls.UpdateReleaseResponse{}
|
|
client, err := getRESTClient()
|
|
// get the release
|
|
release := new(hapi.Release)
|
|
err = client.RESTClient().Get().Namespace(namespace).Resource("releases").Name(req.Name).Do().Into(release)
|
|
if err != nil {
|
|
return resp, err
|
|
}
|
|
release.Spec.Config = req.Values
|
|
release.Spec.DryRun = req.DryRun
|
|
release.Spec.DisableHooks = req.DisableHooks
|
|
release.Spec.Recreate = req.Recreate
|
|
release.Spec.Timeout = req.Timeout
|
|
release.Spec.Chart.Inline = req.Chart
|
|
release.Spec.Version = release.Spec.Version + 1
|
|
// update the release
|
|
updatedRelease := new(hapi.Release)
|
|
err = client.RESTClient().Put().Namespace(namespace).Resource("releases").Name(release.Name).Body(release).Do().Into(updatedRelease)
|
|
if err != nil {
|
|
return resp, err
|
|
}
|
|
resp.Release = new(rs.Release)
|
|
resp.Release.Name = updatedRelease.Name
|
|
resp.Release.Chart = updatedRelease.Spec.Chart.Inline
|
|
resp.Release.Config = updatedRelease.Spec.Config
|
|
resp.Release.Manifest = updatedRelease.Spec.Manifest
|
|
resp.Release.Hooks = updatedRelease.Spec.Hooks
|
|
resp.Release.Version = updatedRelease.Spec.Version
|
|
resp.Release.Info = new(rs.Info)
|
|
resp.Release.Info.Status = new(rs.Status)
|
|
resp.Release.Info.Status.Code = updatedRelease.Status.Code
|
|
resp.Release.Info.Status.Details = updatedRelease.Status.Details
|
|
resp.Release.Info.Status.Notes = updatedRelease.Status.Notes
|
|
return resp, nil
|
|
}
|
|
|
|
// Executes tiller.RollbackRelease RPC.
|
|
func (h *Client) rollback(ctx context.Context, namespace string, req *rls.RollbackReleaseRequest) (*rls.RollbackReleaseResponse, error) {
|
|
/* c, err := grpc.Dial(h.opts.host, grpc.WithInsecure())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer c.Close()
|
|
|
|
rlc := rls.NewReleaseServiceClient(c)
|
|
return rlc.RollbackRelease(ctx, req)*/
|
|
resp := &rls.RollbackReleaseResponse{}
|
|
config, err := getConfig()
|
|
if err != nil {
|
|
return resp, err
|
|
}
|
|
extClient, err := getRESTClient()
|
|
client, err := clientset.NewForConfig(config)
|
|
err = extClient.RESTClient().Get().Namespace(namespace).Resource("releases").Name(req.Name).Do().Error()
|
|
if err != nil {
|
|
return resp, errors.New("Release not found")
|
|
}
|
|
event, err := makeEventForRollBack(req)
|
|
event.ObjectMeta.Namespace = namespace
|
|
event.InvolvedObject.Namespace = namespace
|
|
event.InvolvedObject.Name = (req.Name + "-v" + strconv.Itoa(int(req.Version)))
|
|
event.ObjectMeta.Name = event.InvolvedObject.Name + "-" + RandStringRunes(5)
|
|
if err != nil {
|
|
return resp, err
|
|
}
|
|
err = extClient.RESTClient().Get().Namespace(namespace).Resource("releaseversions").Name(event.InvolvedObject.Name).Do().Error()
|
|
if err != nil {
|
|
return resp, errors.New("Release Version not found")
|
|
}
|
|
_, err = client.Core().Events(namespace).Create(event)
|
|
if err != nil {
|
|
return resp, err
|
|
}
|
|
return resp, nil
|
|
}
|
|
|
|
// Executes tiller.GetReleaseStatus RPC.
|
|
func (h *Client) status(ctx context.Context, namespace string, req *rls.GetReleaseStatusRequest) (*rls.GetReleaseStatusResponse, error) {
|
|
/*
|
|
c, err := grpc.Dial(h.opts.host, grpc.WithInsecure())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer c.Close()
|
|
|
|
rlc := rls.NewReleaseServiceClient(c)
|
|
return rlc.GetReleaseStatus(ctx, req)
|
|
|
|
*/
|
|
resp := &rls.GetReleaseStatusResponse{}
|
|
client, err := getRESTClient()
|
|
if err != nil {
|
|
return resp, err
|
|
}
|
|
release := new(hapi.Release)
|
|
resp.Info = new(rs.Info)
|
|
resp.Info.Status = new(rs.Status)
|
|
if req.Version == 0 {
|
|
err = client.RESTClient().Get().Namespace(namespace).Resource("releases").Name(req.Name).Do().Into(release)
|
|
if err != nil {
|
|
e := client.RESTClient().Get().Namespace(namespace).Resource("releaseversions").Name(req.Name + "-v1").Do().Error()
|
|
if e != nil {
|
|
return resp, err
|
|
} else {
|
|
resp.Namespace = namespace
|
|
resp.Info.Status.Code = rs.Status_DELETED
|
|
return resp, nil
|
|
}
|
|
}
|
|
req.Version = release.Spec.Version
|
|
}
|
|
duration := time.Duration(2) * time.Second
|
|
releaseVersion := new(hapi.ReleaseVersion)
|
|
name := req.Name + "-v" + strconv.Itoa(int(req.Version))
|
|
for i := 0; i <= 20; i++ {
|
|
err = client.RESTClient().Get().Namespace(namespace).Resource("releaseversions").Name(name).Do().Into(releaseVersion)
|
|
if err != nil {
|
|
time.Sleep(duration)
|
|
continue
|
|
} else {
|
|
break
|
|
}
|
|
}
|
|
if err != nil {
|
|
return resp, err
|
|
}
|
|
err = client.RESTClient().Get().Namespace(namespace).Resource("releases").Name(req.Name).Do().Into(release)
|
|
if err != nil {
|
|
return resp, err
|
|
}
|
|
resp.Name = release.Name
|
|
resp.Namespace = release.Namespace
|
|
|
|
resp.Info.Status.Code = release.Status.Code
|
|
resp.Info.Status.Notes = release.Status.Notes
|
|
resp.Info.Status.Details = release.Status.Details
|
|
resp.Info.Status.Resources = GetLatestResourceStatus(release.Namespace, release.Spec.Manifest)
|
|
f, err := ptypes.TimestampProto(release.Status.FirstDeployed.Time)
|
|
if err != nil {
|
|
return resp, err
|
|
}
|
|
resp.Info.FirstDeployed = f
|
|
l, err := ptypes.TimestampProto(release.Status.LastDeployed.Time)
|
|
if err != nil {
|
|
return resp, err
|
|
}
|
|
resp.Info.LastDeployed = l
|
|
|
|
return resp, nil
|
|
}
|
|
|
|
// Executes tiller.GetReleaseContent RPC.
|
|
func (h *Client) content(ctx context.Context, req *rls.GetReleaseContentRequest) (*rls.GetReleaseContentResponse, error) {
|
|
c, err := grpc.Dial(h.opts.host, grpc.WithInsecure())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer c.Close()
|
|
|
|
rlc := rls.NewReleaseServiceClient(c)
|
|
return rlc.GetReleaseContent(ctx, req)
|
|
}
|
|
|
|
// Executes tiller.GetVersion RPC.
|
|
func (h *Client) version(ctx context.Context, req *rls.GetVersionRequest) (*rls.GetVersionResponse, error) {
|
|
c, err := grpc.Dial(h.opts.host, grpc.WithInsecure())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer c.Close()
|
|
|
|
rlc := rls.NewReleaseServiceClient(c)
|
|
return rlc.GetVersion(ctx, req)
|
|
}
|
|
|
|
// Executes tiller.GetHistory RPC.
|
|
func (h *Client) history(ctx context.Context, req *rls.GetHistoryRequest) (*rls.GetHistoryResponse, error) {
|
|
c, err := grpc.Dial(h.opts.host, grpc.WithInsecure())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer c.Close()
|
|
|
|
rlc := rls.NewReleaseServiceClient(c)
|
|
return rlc.GetHistory(ctx, req)
|
|
}
|
|
|
|
func makeReleaseObject(req *rls.InstallReleaseRequest) *hapi.Release {
|
|
release := &hapi.Release{}
|
|
release.TypeMeta.Kind = "Release"
|
|
release.TypeMeta.APIVersion = "helm.sh/v1beta1"
|
|
release.ObjectMeta.Name = req.Name
|
|
release.ObjectMeta.Namespace = req.Namespace
|
|
release.Spec = makeObjectSpec(req)
|
|
return release
|
|
}
|
|
func makeObjectSpec(req *rls.InstallReleaseRequest) hapi.ReleaseSpec {
|
|
spec := hapi.ReleaseSpec{}
|
|
spec.DryRun = req.DryRun
|
|
spec.DisableHooks = req.DisableHooks
|
|
// spec.Reuse = req.ReuseName TODO To enable reuse in installation
|
|
spec.Config = req.Values
|
|
spec.Chart.Inline = new(hapi_chart.Chart)
|
|
spec.Chart.Inline.Files = req.Chart.Files
|
|
spec.Chart.Inline.Metadata = req.Chart.Metadata
|
|
spec.Chart.Inline.Templates = req.Chart.Templates
|
|
spec.Chart.Inline.Values = req.Chart.Values
|
|
return spec
|
|
}
|
|
|
|
func getConfig() (*restclient.Config, error) {
|
|
rules := clientcmd.NewDefaultClientConfigLoadingRules()
|
|
rules.DefaultClientConfig = &clientcmd.DefaultClientConfig
|
|
overrides := &clientcmd.ConfigOverrides{ClusterDefaults: clientcmd.ClusterDefaults}
|
|
config, err := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(rules, overrides).ClientConfig()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Could not get kubernetes config: %s", err)
|
|
}
|
|
return config, nil
|
|
}
|
|
|
|
func getRESTClient() (*cs.ExtensionsClient, error) {
|
|
c, err := getConfig()
|
|
config := *c
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
client, err := cs.NewExtensionsForConfig(&config)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return client, nil
|
|
}
|
|
|
|
type RollbackReq struct {
|
|
// dry_run, if true, will run through the release logic but no create
|
|
DryRun bool `protobuf:"varint,2,opt,name=dry_run,json=dryRun" json:"dry_run,omitempty"`
|
|
// DisableHooks causes the server to skip running any hooks for the rollback
|
|
DisableHooks bool `protobuf:"varint,3,opt,name=disable_hooks,json=disableHooks" json:"disable_hooks,omitempty"`
|
|
// Performs pods restart for resources if applicable
|
|
Recreate bool `protobuf:"varint,5,opt,name=recreate" json:"recreate,omitempty"`
|
|
// timeout specifies the max amount of time any kubernetes client command can run.
|
|
Timeout int64 `protobuf:"varint,6,opt,name=timeout" json:"timeout,omitempty"`
|
|
}
|
|
|
|
func makeEventForRollBack(req *rls.RollbackReleaseRequest) (*api.Event, error) {
|
|
r := RollbackReq{
|
|
DryRun: req.DryRun,
|
|
Recreate: req.Recreate,
|
|
DisableHooks: req.DisableHooks,
|
|
Timeout: req.Timeout,
|
|
}
|
|
message, err := json.Marshal(r)
|
|
if err != nil {
|
|
return &api.Event{}, err
|
|
}
|
|
event := &api.Event{
|
|
InvolvedObject: api.ObjectReference{
|
|
Kind: "release",
|
|
},
|
|
Reason: "releaseRollback",
|
|
Message: string(message),
|
|
Type: api.EventTypeNormal,
|
|
Count: 1,
|
|
}
|
|
return event, nil
|
|
}
|
|
|
|
var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
|
|
|
|
func RandStringRunes(n int) string {
|
|
b := make([]rune, n)
|
|
for i := range b {
|
|
b[i] = letterRunes[rand.Intn(len(letterRunes))]
|
|
}
|
|
return string(b)
|
|
}
|
|
|
|
func GetLatestResourceStatus(namespace, manifest string) string {
|
|
KubeClient := kube.New(nil)
|
|
resource, err := KubeClient.Get(namespace, bytes.NewBufferString(manifest))
|
|
if err != nil {
|
|
log.Println(err)
|
|
return ""
|
|
}
|
|
return resource
|
|
}
|