diff --git a/pkg/tiller/release_install.go b/pkg/tiller/release_install.go index 973da3581..97cd1b86c 100644 --- a/pkg/tiller/release_install.go +++ b/pkg/tiller/release_install.go @@ -17,6 +17,7 @@ limitations under the License. package tiller import ( + "errors" "fmt" "strings" @@ -60,6 +61,12 @@ func (s *ReleaseServer) prepareRelease(req *services.InstallReleaseRequest) (*re return nil, errMissingChart } + err := s.isValidNamespace(req.Namespace) + if err != nil { + errString := fmt.Sprintf("invalid release namespace, err=%s", err.Error()) + return nil, errors.New(errString) + } + name, err := s.uniqName(req.Name, req.ReuseName) if err != nil { return nil, err diff --git a/pkg/tiller/release_install_test.go b/pkg/tiller/release_install_test.go index f5e84d870..ef7b36cf7 100644 --- a/pkg/tiller/release_install_test.go +++ b/pkg/tiller/release_install_test.go @@ -515,3 +515,21 @@ func TestInstallRelease_Description(t *testing.T) { t.Errorf("Expected description %q. Got %q", customDescription, desc) } } +func TestInstallRelease_ReleaseNamespaceNotExist(t *testing.T) { + c := helm.NewContext() + rs := rsFixtureConfigMapStorage() + + req := installRequest( + withNamespace("noSpaced"), + ) + + _, err := rs.InstallRelease(c, req) + if err == nil { + t.Fatalf("Expected to fail because of the namespace is not exist") + } + + expect := "invalid release namespace" + if !strings.Contains(err.Error(), expect) { + t.Errorf("Expected %q equal to %q", err.Error(), expect) + } +} diff --git a/pkg/tiller/release_server.go b/pkg/tiller/release_server.go index f5e96ed00..f2e4b555c 100644 --- a/pkg/tiller/release_server.go +++ b/pkg/tiller/release_server.go @@ -36,6 +36,7 @@ import ( "k8s.io/helm/pkg/proto/hapi/release" "k8s.io/helm/pkg/proto/hapi/services" relutil "k8s.io/helm/pkg/releaseutil" + "k8s.io/helm/pkg/storage/driver" "k8s.io/helm/pkg/tiller/environment" "k8s.io/helm/pkg/timeconv" "k8s.io/helm/pkg/version" @@ -452,6 +453,15 @@ func (s *ReleaseServer) deleteHookByPolicy(h *release.Hook, policy string, name, return nil } +func (s *ReleaseServer) isValidNamespace(name string) error { + // if the storage is not configmap, do not check the namespace + if s.env.Releases.Name() != driver.ConfigMapsDriverName { + return nil + } + _, err := s.clientset.Core().Namespaces().Get(name, metav1.GetOptions{}) + return err +} + // hookShouldBeDeleted determines whether the defined hook deletion policy matches the hook deletion polices // supported by helm. If so, mark the hook as one should be deleted. func hookHasDeletePolicy(h *release.Hook, policy string) bool { diff --git a/pkg/tiller/release_server_test.go b/pkg/tiller/release_server_test.go index 311f55b30..b58d4ea99 100644 --- a/pkg/tiller/release_server_test.go +++ b/pkg/tiller/release_server_test.go @@ -33,6 +33,7 @@ import ( "google.golang.org/grpc/metadata" "k8s.io/api/core/v1" "k8s.io/cli-runtime/pkg/genericclioptions/resource" + "k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes/fake" "k8s.io/helm/pkg/helm" @@ -120,7 +121,13 @@ type chartOptions struct { type chartOption func(*chartOptions) func rsFixture() *ReleaseServer { - return NewReleaseServer(MockEnvironment(), fake.NewSimpleClientset(), false) + clientset := fake.NewSimpleClientset() + return NewReleaseServer(MockEnvironment(driver.MemoryDriverName, clientset), clientset, false) +} + +func rsFixtureConfigMapStorage() *ReleaseServer { + clientset := fake.NewSimpleClientset() + return NewReleaseServer(MockEnvironment(driver.ConfigMapsDriverName, clientset), clientset, false) } func buildChart(opts ...chartOption) *chart.Chart { @@ -221,6 +228,12 @@ func withChart(chartOpts ...chartOption) installOption { } } +func withNamespace(namepace string) installOption { + return func(opts *installOptions) { + opts.Namespace = namepace + } +} + func installRequest(opts ...installOption) *services.InstallReleaseRequest { reqOpts := &installOptions{ &services.InstallReleaseRequest{ @@ -462,9 +475,13 @@ func releaseWithKeepStub(rlsName string) *release.Release { } } -func MockEnvironment() *environment.Environment { +func MockEnvironment(storageType string, clientset kubernetes.Interface) *environment.Environment { e := environment.New() - e.Releases = storage.Init(driver.NewMemory()) + if storageType == driver.ConfigMapsDriverName { + e.Releases = storage.Init(driver.NewConfigMaps(clientset.CoreV1().ConfigMaps("default"))) + } else { + e.Releases = storage.Init(driver.NewMemory()) + } e.KubeClient = &environment.PrintingKubeClient{Out: ioutil.Discard} return e }