From a4d05fd2b2a9706775dd3ad092c954194c3fa881 Mon Sep 17 00:00:00 2001 From: fibonacci1729 Date: Mon, 22 May 2017 11:37:55 -0600 Subject: [PATCH] ref(tiller): refactor tiller APIs into logical files *ReleaseServer.UninstallRelease -> tiller/release_uninstall.go *ReleaseServer.ListReleases -> tiller/release_list.go --- pkg/tiller/release_list.go | 141 +++++++++++++++++++++ pkg/tiller/release_server.go | 212 -------------------------------- pkg/tiller/release_uninstall.go | 124 +++++++++++++++++++ 3 files changed, 265 insertions(+), 212 deletions(-) create mode 100644 pkg/tiller/release_list.go create mode 100644 pkg/tiller/release_uninstall.go diff --git a/pkg/tiller/release_list.go b/pkg/tiller/release_list.go new file mode 100644 index 000000000..14d5c0d38 --- /dev/null +++ b/pkg/tiller/release_list.go @@ -0,0 +1,141 @@ +/* +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 tiller + +import ( + "fmt" + "k8s.io/helm/pkg/proto/hapi/release" + "k8s.io/helm/pkg/proto/hapi/services" + relutil "k8s.io/helm/pkg/releaseutil" + "regexp" +) + +// ListReleases lists the releases found by the server. +func (s *ReleaseServer) ListReleases(req *services.ListReleasesRequest, stream services.ReleaseService_ListReleasesServer) error { + if len(req.StatusCodes) == 0 { + req.StatusCodes = []release.Status_Code{release.Status_DEPLOYED} + } + + //rels, err := s.env.Releases.ListDeployed() + rels, err := s.env.Releases.ListFilterAll(func(r *release.Release) bool { + for _, sc := range req.StatusCodes { + if sc == r.Info.Status.Code { + return true + } + } + return false + }) + if err != nil { + return err + } + + if req.Namespace != "" { + rels, err = filterByNamespace(req.Namespace, rels) + if err != nil { + return err + } + } + + if len(req.Filter) != 0 { + rels, err = filterReleases(req.Filter, rels) + if err != nil { + return err + } + } + + total := int64(len(rels)) + + switch req.SortBy { + case services.ListSort_NAME: + relutil.SortByName(rels) + case services.ListSort_LAST_RELEASED: + relutil.SortByDate(rels) + } + + if req.SortOrder == services.ListSort_DESC { + ll := len(rels) + rr := make([]*release.Release, ll) + for i, item := range rels { + rr[ll-i-1] = item + } + rels = rr + } + + l := int64(len(rels)) + if req.Offset != "" { + + i := -1 + for ii, cur := range rels { + if cur.Name == req.Offset { + i = ii + } + } + if i == -1 { + return fmt.Errorf("offset %q not found", req.Offset) + } + + if len(rels) < i { + return fmt.Errorf("no items after %q", req.Offset) + } + + rels = rels[i:] + l = int64(len(rels)) + } + + if req.Limit == 0 { + req.Limit = ListDefaultLimit + } + + next := "" + if l > req.Limit { + next = rels[req.Limit].Name + rels = rels[0:req.Limit] + l = int64(len(rels)) + } + + res := &services.ListReleasesResponse{ + Next: next, + Count: l, + Total: total, + Releases: rels, + } + return stream.Send(res) +} + +func filterByNamespace(namespace string, rels []*release.Release) ([]*release.Release, error) { + matches := []*release.Release{} + for _, r := range rels { + if namespace == r.Namespace { + matches = append(matches, r) + } + } + return matches, nil +} + +func filterReleases(filter string, rels []*release.Release) ([]*release.Release, error) { + preg, err := regexp.Compile(filter) + if err != nil { + return rels, err + } + matches := []*release.Release{} + for _, r := range rels { + if preg.MatchString(r.Name) { + matches = append(matches, r) + } + } + return matches, nil +} diff --git a/pkg/tiller/release_server.go b/pkg/tiller/release_server.go index 79ca0f02b..6d1eef837 100644 --- a/pkg/tiller/release_server.go +++ b/pkg/tiller/release_server.go @@ -104,122 +104,6 @@ func NewReleaseServer(env *environment.Environment, clientset internalclientset. } } -// ListReleases lists the releases found by the server. -func (s *ReleaseServer) ListReleases(req *services.ListReleasesRequest, stream services.ReleaseService_ListReleasesServer) error { - if len(req.StatusCodes) == 0 { - req.StatusCodes = []release.Status_Code{release.Status_DEPLOYED} - } - - //rels, err := s.env.Releases.ListDeployed() - rels, err := s.env.Releases.ListFilterAll(func(r *release.Release) bool { - for _, sc := range req.StatusCodes { - if sc == r.Info.Status.Code { - return true - } - } - return false - }) - if err != nil { - return err - } - - if req.Namespace != "" { - rels, err = filterByNamespace(req.Namespace, rels) - if err != nil { - return err - } - } - - if len(req.Filter) != 0 { - rels, err = filterReleases(req.Filter, rels) - if err != nil { - return err - } - } - - total := int64(len(rels)) - - switch req.SortBy { - case services.ListSort_NAME: - relutil.SortByName(rels) - case services.ListSort_LAST_RELEASED: - relutil.SortByDate(rels) - } - - if req.SortOrder == services.ListSort_DESC { - ll := len(rels) - rr := make([]*release.Release, ll) - for i, item := range rels { - rr[ll-i-1] = item - } - rels = rr - } - - l := int64(len(rels)) - if req.Offset != "" { - - i := -1 - for ii, cur := range rels { - if cur.Name == req.Offset { - i = ii - } - } - if i == -1 { - return fmt.Errorf("offset %q not found", req.Offset) - } - - if len(rels) < i { - return fmt.Errorf("no items after %q", req.Offset) - } - - rels = rels[i:] - l = int64(len(rels)) - } - - if req.Limit == 0 { - req.Limit = ListDefaultLimit - } - - next := "" - if l > req.Limit { - next = rels[req.Limit].Name - rels = rels[0:req.Limit] - l = int64(len(rels)) - } - - res := &services.ListReleasesResponse{ - Next: next, - Count: l, - Total: total, - Releases: rels, - } - return stream.Send(res) -} - -func filterByNamespace(namespace string, rels []*release.Release) ([]*release.Release, error) { - matches := []*release.Release{} - for _, r := range rels { - if namespace == r.Namespace { - matches = append(matches, r) - } - } - return matches, nil -} - -func filterReleases(filter string, rels []*release.Release) ([]*release.Release, error) { - preg, err := regexp.Compile(filter) - if err != nil { - return rels, err - } - matches := []*release.Release{} - for _, r := range rels { - if preg.MatchString(r.Name) { - matches = append(matches, r) - } - } - return matches, nil -} - // UpdateRelease takes an existing release and new information, and upgrades the release. func (s *ReleaseServer) UpdateRelease(c ctx.Context, req *services.UpdateReleaseRequest) (*services.UpdateReleaseResponse, error) { err := s.env.Releases.LockRelease(req.Name) @@ -808,102 +692,6 @@ func (s *ReleaseServer) purgeReleases(rels ...*release.Release) error { return nil } -// UninstallRelease deletes all of the resources associated with this release, and marks the release DELETED. -func (s *ReleaseServer) UninstallRelease(c ctx.Context, req *services.UninstallReleaseRequest) (*services.UninstallReleaseResponse, error) { - err := s.env.Releases.LockRelease(req.Name) - if err != nil { - return nil, err - } - defer s.env.Releases.UnlockRelease(req.Name) - - if !ValidName.MatchString(req.Name) { - s.Log("uninstall: Release not found: %s", req.Name) - return nil, errMissingRelease - } - - if len(req.Name) > releaseNameMaxLen { - return nil, fmt.Errorf("release name %q exceeds max length of %d", req.Name, releaseNameMaxLen) - } - - rels, err := s.env.Releases.History(req.Name) - if err != nil { - s.Log("uninstall: Release not loaded: %s", req.Name) - return nil, err - } - if len(rels) < 1 { - return nil, errMissingRelease - } - - relutil.SortByRevision(rels) - rel := rels[len(rels)-1] - - // TODO: Are there any cases where we want to force a delete even if it's - // already marked deleted? - if rel.Info.Status.Code == release.Status_DELETED { - if req.Purge { - if err := s.purgeReleases(rels...); err != nil { - s.Log("uninstall: Failed to purge the release: %s", err) - return nil, err - } - return &services.UninstallReleaseResponse{Release: rel}, nil - } - return nil, fmt.Errorf("the release named %q is already deleted", req.Name) - } - - s.Log("uninstall: Deleting %s", req.Name) - rel.Info.Status.Code = release.Status_DELETING - rel.Info.Deleted = timeconv.Now() - rel.Info.Description = "Deletion in progress (or silently failed)" - res := &services.UninstallReleaseResponse{Release: rel} - - if !req.DisableHooks { - if err := s.execHook(rel.Hooks, rel.Name, rel.Namespace, hooks.PreDelete, req.Timeout); err != nil { - return res, err - } - } - - // From here on out, the release is currently considered to be in Status_DELETING - // state. - if err := s.env.Releases.Update(rel); err != nil { - s.Log("uninstall: Failed to store updated release: %s", err) - } - - kept, errs := s.ReleaseModule.Delete(rel, req, s.env) - res.Info = kept - - es := make([]string, 0, len(errs)) - for _, e := range errs { - s.Log("error: %v", e) - es = append(es, e.Error()) - } - - if !req.DisableHooks { - if err := s.execHook(rel.Hooks, rel.Name, rel.Namespace, hooks.PostDelete, req.Timeout); err != nil { - es = append(es, err.Error()) - } - } - - rel.Info.Status.Code = release.Status_DELETED - rel.Info.Description = "Deletion complete" - - if req.Purge { - err := s.purgeReleases(rels...) - if err != nil { - s.Log("uninstall: Failed to purge the release: %s", err) - } - return res, err - } - - if err := s.env.Releases.Update(rel); err != nil { - s.Log("uninstall: Failed to store updated release: %s", err) - } - - if len(es) > 0 { - return res, fmt.Errorf("deletion completed with %d error(s): %s", len(es), strings.Join(es, "; ")) - } - return res, nil -} - func validateManifest(c environment.KubeClient, ns string, manifest []byte) error { r := bytes.NewReader(manifest) _, err := c.BuildUnstructured(ns, r) diff --git a/pkg/tiller/release_uninstall.go b/pkg/tiller/release_uninstall.go new file mode 100644 index 000000000..a16a8edcf --- /dev/null +++ b/pkg/tiller/release_uninstall.go @@ -0,0 +1,124 @@ +/* +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 tiller + +import ( + "fmt" + ctx "golang.org/x/net/context" + "k8s.io/helm/pkg/hooks" + "k8s.io/helm/pkg/proto/hapi/release" + "k8s.io/helm/pkg/proto/hapi/services" + relutil "k8s.io/helm/pkg/releaseutil" + "k8s.io/helm/pkg/timeconv" + "strings" +) + +// UninstallRelease deletes all of the resources associated with this release, and marks the release DELETED. +func (s *ReleaseServer) UninstallRelease(c ctx.Context, req *services.UninstallReleaseRequest) (*services.UninstallReleaseResponse, error) { + err := s.env.Releases.LockRelease(req.Name) + if err != nil { + return nil, err + } + defer s.env.Releases.UnlockRelease(req.Name) + + if !ValidName.MatchString(req.Name) { + s.Log("uninstall: Release not found: %s", req.Name) + return nil, errMissingRelease + } + + if len(req.Name) > releaseNameMaxLen { + return nil, fmt.Errorf("release name %q exceeds max length of %d", req.Name, releaseNameMaxLen) + } + + rels, err := s.env.Releases.History(req.Name) + if err != nil { + s.Log("uninstall: Release not loaded: %s", req.Name) + return nil, err + } + if len(rels) < 1 { + return nil, errMissingRelease + } + + relutil.SortByRevision(rels) + rel := rels[len(rels)-1] + + // TODO: Are there any cases where we want to force a delete even if it's + // already marked deleted? + if rel.Info.Status.Code == release.Status_DELETED { + if req.Purge { + if err := s.purgeReleases(rels...); err != nil { + s.Log("uninstall: Failed to purge the release: %s", err) + return nil, err + } + return &services.UninstallReleaseResponse{Release: rel}, nil + } + return nil, fmt.Errorf("the release named %q is already deleted", req.Name) + } + + s.Log("uninstall: Deleting %s", req.Name) + rel.Info.Status.Code = release.Status_DELETING + rel.Info.Deleted = timeconv.Now() + rel.Info.Description = "Deletion in progress (or silently failed)" + res := &services.UninstallReleaseResponse{Release: rel} + + if !req.DisableHooks { + if err := s.execHook(rel.Hooks, rel.Name, rel.Namespace, hooks.PreDelete, req.Timeout); err != nil { + return res, err + } + } + + // From here on out, the release is currently considered to be in Status_DELETING + // state. + if err := s.env.Releases.Update(rel); err != nil { + s.Log("uninstall: Failed to store updated release: %s", err) + } + + kept, errs := s.ReleaseModule.Delete(rel, req, s.env) + res.Info = kept + + es := make([]string, 0, len(errs)) + for _, e := range errs { + s.Log("error: %v", e) + es = append(es, e.Error()) + } + + if !req.DisableHooks { + if err := s.execHook(rel.Hooks, rel.Name, rel.Namespace, hooks.PostDelete, req.Timeout); err != nil { + es = append(es, err.Error()) + } + } + + rel.Info.Status.Code = release.Status_DELETED + rel.Info.Description = "Deletion complete" + + if req.Purge { + err := s.purgeReleases(rels...) + if err != nil { + s.Log("uninstall: Failed to purge the release: %s", err) + } + return res, err + } + + if err := s.env.Releases.Update(rel); err != nil { + s.Log("uninstall: Failed to store updated release: %s", err) + } + + if len(es) > 0 { + return res, fmt.Errorf("deletion completed with %d error(s): %s", len(es), strings.Join(es, "; ")) + } + return res, nil +}