Unverified Commit 0c1422e4 authored by bryanl's avatar bryanl
Browse files

moved env to pkg/env


Signed-off-by: default avatarbryanl <bryanliles@gmail.com>
parent 3043f720
// Copyright 2018 The kubecfg authors // Copyright 2018 The ksonnet authors
// //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
...@@ -13,65 +13,50 @@ ...@@ -13,65 +13,50 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
package env package actions
import ( import (
"github.com/ksonnet/ksonnet/component"
"github.com/ksonnet/ksonnet/metadata/app" "github.com/ksonnet/ksonnet/metadata/app"
) )
const ( // RunComponentRm runs `component list`
// primary environment files. func RunComponentRm(m map[string]interface{}) error {
envFileName = "main.jsonnet" cr, err := NewComponentRm(m)
paramsFileName = "params.libsonnet" if err != nil {
return err
// envRoot is the name for the environment root. }
envRoot = "environments"
)
// Env represents a ksonnet environment. return cr.Run()
type Env struct {
// Name is the environment name.
Name string
// KubernetesVersion is the version of Kubernetes for this environment.
KubernetesVersion string
// Destination is the cluster destination for this environment.
Destination Destination
// Targets are the component namespaces that will be installed.
Targets []string
} }
func envFromSpec(name string, envSpec *app.EnvironmentSpec) *Env { // ComponentRm create a list of components in a namespace.
return &Env{ type ComponentRm struct {
Name: name, app app.App
KubernetesVersion: envSpec.KubernetesVersion, name string
Destination: NewDestination(envSpec.Destination.Server, envSpec.Destination.Namespace),
Targets: envSpec.Targets, componentDeleteFn func(app.App, string) error
}
} }
// List lists all environments for the current ksonnet application. // NewComponentRm creates an instance of ComponentRm.
func List(ksApp app.App) (map[string]Env, error) { func NewComponentRm(m map[string]interface{}) (*ComponentRm, error) {
envs := make(map[string]Env) ol := newOptionLoader(m)
specs, err := ksApp.Environments() cr := &ComponentRm{
if err != nil { app: ol.loadApp(),
return nil, err name: ol.loadString(OptionComponentName),
componentDeleteFn: component.Delete,
} }
for name, spec := range specs { if ol.err != nil {
env := envFromSpec(name, spec) return nil, ol.err
envs[name] = *env
} }
return envs, nil return cr, nil
} }
// Retrieve retrieves an environment by name. // Run runs the ComponentRm action.
func Retrieve(ksApp app.App, name string) (*Env, error) { func (cr *ComponentRm) Run() error {
envSpec, err := ksApp.Environment(name) return cr.componentDeleteFn(cr.app, cr.name)
if err != nil {
return nil, err
}
return envFromSpec(name, envSpec), nil
} }
// Copyright 2018 The ksonnet 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.
package actions
import (
"testing"
"github.com/ksonnet/ksonnet/metadata/app"
amocks "github.com/ksonnet/ksonnet/metadata/app/mocks"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestComponentRm(t *testing.T) {
withApp(t, func(appMock *amocks.App) {
name := "component-name"
var didDelete bool
deleteFn := func(a app.App, componentName string) error {
assert.Equal(t, componentName, name)
didDelete = true
return nil
}
in := map[string]interface{}{
OptionApp: appMock,
OptionComponentName: name,
}
a, err := NewComponentRm(in)
require.NoError(t, err)
a.componentDeleteFn = deleteFn
err = a.Run()
require.NoError(t, err)
assert.True(t, didDelete)
})
}
...@@ -16,14 +16,8 @@ ...@@ -16,14 +16,8 @@
package actions package actions
import ( import (
"github.com/ksonnet/ksonnet/env"
"github.com/ksonnet/ksonnet/metadata/app" "github.com/ksonnet/ksonnet/metadata/app"
) "github.com/ksonnet/ksonnet/pkg/env"
const (
baseLibsonnetFile = "base.libsonnet"
componentsDir = "components"
paramsFileName = "params.libsonnet"
) )
// RunEnvAdd runs `env add` // RunEnvAdd runs `env add`
...@@ -79,8 +73,8 @@ func (ea *EnvAdd) Run() error { ...@@ -79,8 +73,8 @@ func (ea *EnvAdd) Run() error {
destination, destination,
ea.envName, ea.envName,
ea.k8sSpecFlag, ea.k8sSpecFlag,
env.DefaultOverrideData(), env.DefaultOverrideData,
env.DefaultParamsData(), env.DefaultParamsData,
ea.isOverride, ea.isOverride,
) )
} }
...@@ -18,9 +18,9 @@ package actions ...@@ -18,9 +18,9 @@ package actions
import ( import (
"testing" "testing"
"github.com/ksonnet/ksonnet/env"
"github.com/ksonnet/ksonnet/metadata/app" "github.com/ksonnet/ksonnet/metadata/app"
amocks "github.com/ksonnet/ksonnet/metadata/app/mocks" amocks "github.com/ksonnet/ksonnet/metadata/app/mocks"
"github.com/ksonnet/ksonnet/pkg/env"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
......
...@@ -16,8 +16,8 @@ ...@@ -16,8 +16,8 @@
package actions package actions
import ( import (
"github.com/ksonnet/ksonnet/env"
"github.com/ksonnet/ksonnet/metadata/app" "github.com/ksonnet/ksonnet/metadata/app"
"github.com/ksonnet/ksonnet/pkg/env"
) )
// RunEnvRm runs `env rm` // RunEnvRm runs `env rm`
......
...@@ -16,8 +16,8 @@ ...@@ -16,8 +16,8 @@
package actions package actions
import ( import (
"github.com/ksonnet/ksonnet/env"
"github.com/ksonnet/ksonnet/metadata/app" "github.com/ksonnet/ksonnet/metadata/app"
"github.com/ksonnet/ksonnet/pkg/env"
) )
// EnvSetNamespace is an option for setting a new namespace name. // EnvSetNamespace is an option for setting a new namespace name.
......
...@@ -20,9 +20,9 @@ import ( ...@@ -20,9 +20,9 @@ import (
"strings" "strings"
"github.com/ksonnet/ksonnet/component" "github.com/ksonnet/ksonnet/component"
"github.com/ksonnet/ksonnet/env"
"github.com/ksonnet/ksonnet/metadata/app" "github.com/ksonnet/ksonnet/metadata/app"
mp "github.com/ksonnet/ksonnet/metadata/params" mp "github.com/ksonnet/ksonnet/metadata/params"
"github.com/ksonnet/ksonnet/pkg/env"
"github.com/ksonnet/ksonnet/pkg/params" "github.com/ksonnet/ksonnet/pkg/params"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
......
...@@ -25,6 +25,7 @@ type initName int ...@@ -25,6 +25,7 @@ type initName int
const ( const (
actionApply initName = iota actionApply initName = iota
actionComponentList actionComponentList
actionComponentRm
actionDelete actionDelete
actionDiff actionDiff
actionEnvAdd actionEnvAdd
...@@ -62,6 +63,7 @@ var ( ...@@ -62,6 +63,7 @@ var (
actionFns = map[initName]actionFn{ actionFns = map[initName]actionFn{
actionApply: actions.RunApply, actionApply: actions.RunApply,
actionComponentList: actions.RunComponentList, actionComponentList: actions.RunComponentList,
actionComponentRm: actions.RunComponentRm,
// actionDelete // actionDelete
// actionDiff // actionDiff
actionEnvAdd: actions.RunEnvAdd, actionEnvAdd: actions.RunEnvAdd,
...@@ -102,10 +104,3 @@ func runAction(name initName, args map[string]interface{}) error { ...@@ -102,10 +104,3 @@ func runAction(name initName, args map[string]interface{}) error {
return fn(args) return fn(args)
} }
var (
actionMap = map[initName]interface{}{
actionInit: actions.RunInit,
actionValidate: actions.RunValidate,
}
)
...@@ -32,22 +32,6 @@ var ( ...@@ -32,22 +32,6 @@ var (
) )
const ( const (
// AnnotationGcTag annotation that triggers
// garbage collection. Objects with value equal to
// command-line flag that are *not* in config will be deleted.
AnnotationGcTag = "kubecfg.ksonnet.io/garbage-collect-tag"
// AnnotationGcStrategy controls gc logic. Current values:
// `auto` (default if absent) - do garbage collection
// `ignore` - never garbage collect this object
AnnotationGcStrategy = "kubecfg.ksonnet.io/garbage-collect-strategy"
// GcStrategyAuto is the default automatic gc logic
GcStrategyAuto = "auto"
// GcStrategyIgnore means this object should be ignored by garbage collection
GcStrategyIgnore = "ignore"
applyShortDesc = "Apply local Kubernetes manifests (components) to remote clusters" applyShortDesc = "Apply local Kubernetes manifests (components) to remote clusters"
) )
......
...@@ -18,7 +18,7 @@ package cmd ...@@ -18,7 +18,7 @@ package cmd
import ( import (
"fmt" "fmt"
"github.com/ksonnet/ksonnet/pkg/kubecfg" "github.com/ksonnet/ksonnet/actions"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
...@@ -30,11 +30,12 @@ var componentRmCmd = &cobra.Command{ ...@@ -30,11 +30,12 @@ var componentRmCmd = &cobra.Command{
return fmt.Errorf("'component rm' takes a single argument, that is the name of the component") return fmt.Errorf("'component rm' takes a single argument, that is the name of the component")
} }
component := args[0] m := map[string]interface{}{
actions.OptionApp: ka,
actions.OptionComponentName: args[0],
}
// TODO: move this to actions return runAction(actionComponentRm, m)
c := kubecfg.NewComponentRmCmd(component)
return c.Run()
}, },
Long: `Delete a component from the ksonnet application. This is equivalent to deleting the Long: `Delete a component from the ksonnet application. This is equivalent to deleting the
component file in the components directory and cleaning up all component component file in the components directory and cleaning up all component
......
...@@ -17,22 +17,22 @@ package cmd ...@@ -17,22 +17,22 @@ package cmd
import ( import (
"testing" "testing"
"github.com/ksonnet/ksonnet/actions"
) )
func Test_componentRmCmd(t *testing.T) { func Test_componentRmCmd(t *testing.T) {
cases := []cmdTestCase{
{
name: "in general",
args: []string{"component", "rm", "name"},
action: actionComponentRm,
expected: map[string]interface{}{
actions.OptionApp: ka,
actions.OptionComponentName: "name",
},
},
}
// TODO: re-enable when component rm is an action runTestCmd(t, cases)
// cases := []cmdTestCase{
// {
// name: "in general",
// args: []string{"component", "rm", "name"},
// action: actionComponentList,
// expected: map[string]interface{}{
// actions.OptionApp: ka,
// actions.OptionComponentName: "name",
// },
// },
// }
// runTestCmd(t, cases)
} }
...@@ -48,20 +48,11 @@ type cmdTestCase struct { ...@@ -48,20 +48,11 @@ type cmdTestCase struct {
expected map[string]interface{} expected map[string]interface{}
} }
func stubCmdOverride() (*map[string]interface{}, func(map[string]interface{}) error) { type stubCmdOverride struct {
var got *map[string]interface{}
return got, func(m map[string]interface{}) error {
got = &m
return nil
}
}
type stubCmdOverride2 struct {
got map[string]interface{} got map[string]interface{}
} }
func (s *stubCmdOverride2) override(m map[string]interface{}) error { func (s *stubCmdOverride) override(m map[string]interface{}) error {
s.got = m s.got = m
return nil return nil
} }
...@@ -69,7 +60,7 @@ func (s *stubCmdOverride2) override(m map[string]interface{}) error { ...@@ -69,7 +60,7 @@ func (s *stubCmdOverride2) override(m map[string]interface{}) error {
func runTestCmd(t *testing.T, cases []cmdTestCase) { func runTestCmd(t *testing.T, cases []cmdTestCase) {
for _, tc := range cases { for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) { t.Run(tc.name, func(t *testing.T) {
s := stubCmdOverride2{} s := stubCmdOverride{}
withCmd(tc.action, s.override, func() { withCmd(tc.action, s.override, func() {
......
...@@ -28,9 +28,9 @@ import ( ...@@ -28,9 +28,9 @@ import (
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"github.com/ksonnet/ksonnet/env"
"github.com/ksonnet/ksonnet/metadata" "github.com/ksonnet/ksonnet/metadata"
"github.com/ksonnet/ksonnet/metadata/app" "github.com/ksonnet/ksonnet/metadata/app"
"github.com/ksonnet/ksonnet/pkg/env"
"github.com/ksonnet/ksonnet/pkg/pipeline" "github.com/ksonnet/ksonnet/pkg/pipeline"
"github.com/ksonnet/ksonnet/plugin" "github.com/ksonnet/ksonnet/plugin"
str "github.com/ksonnet/ksonnet/strings" str "github.com/ksonnet/ksonnet/strings"
...@@ -175,15 +175,6 @@ func runPlugin(p plugin.Plugin, args []string) error { ...@@ -175,15 +175,6 @@ func runPlugin(p plugin.Plugin, args []string) error {
return cmd.Run() return cmd.Run()
} }
func ksApp() (app.App, error) {
cwd, err := os.Getwd()
if err != nil {
return nil, err
}
return app.Load(appFs, cwd)
}
func logLevel(verbosity int) log.Level { func logLevel(verbosity int) log.Level {
switch verbosity { switch verbosity {
case 0: case 0:
......
...@@ -149,32 +149,6 @@ func isComponentDir(fs afero.Fs, path string) (bool, error) { ...@@ -149,32 +149,6 @@ func isComponentDir(fs afero.Fs, path string) (bool, error) {
return false, nil return false, nil
} }
// MakePathsByNamespace creates a map of component paths categorized by namespace.
func MakePathsByNamespace(a app.App, env string) (map[Namespace][]string, error) {
paths, err := MakePaths(a, env)
if err != nil {
return nil, err
}
m := make(map[Namespace][]string)
for i := range paths {
prefix := a.Root() + "/components/"
if strings.HasSuffix(a.Root(), "/") {
prefix = a.Root() + "components/"
}
path := strings.TrimPrefix(paths[i], prefix)
ns, _ := ExtractNamespacedComponent(a, path)
if _, ok := m[ns]; !ok {
m[ns] = make([]string, 0)
}
m[ns] = append(m[ns], paths[i])
}
return m, nil
}
// MakePaths creates a slice of component paths // MakePaths creates a slice of component paths
func MakePaths(a app.App, env string) ([]string, error) { func MakePaths(a app.App, env string) ([]string, error) {
cpl, err := newComponentPathLocator(a, env) cpl, err := newComponentPathLocator(a, env)
......
// Copyright 2018 The ksonnet 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.
package component
import (
"path/filepath"
"github.com/ksonnet/ksonnet/metadata/app"
param "github.com/ksonnet/ksonnet/metadata/params"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
"github.com/spf13/afero"
)
// Delete deletes the component file and all references.
// Write operations will happen at the end to minimal-ize failures that leave
// the directory structure in a half-finished state.
func Delete(a app.App, name string) error {
log.Debugf("deleting component %s", name)
componentPath, err := Path(a, name)
if err != nil {
return err
}
ns, _ := ExtractNamespacedComponent(a, name)
// Build the new component/params.libsonnet file.
componentParamsFile, err := afero.ReadFile(a.Fs(), ns.ParamsPath())
if err != nil {
return err
}
componentJsonnet, err := param.DeleteComponent(name, string(componentParamsFile))
if err != nil {
return err
}
// Build the new environment/<env>/params.libsonnet files.
// environment name -> jsonnet
envParams := make(map[string]string)
envs, err := a.Environments()
if err != nil {
return err
}
for envName, env := range envs {
var updated string
updated, err = collectEnvParams(a, env, name, envName)
if err != nil {
return err
}
envParams[envName] = updated
}
//
// Delete the component references.
//
log.Infof("Removing component parameter references ...")
// Remove the references in component/params.libsonnet.
log.Debugf("... deleting references in %s", ns.ParamsPath())
err = afero.WriteFile(a.Fs(), ns.ParamsPath(), []byte(componentJsonnet), defaultFilePermissions)
if err != nil {
return err
}
if err = updateEnvParam(a, envs, envParams); err != nil {
return errors.Wrap(err, "writing environment params")
}
//
// Delete the component file in components/.
//