Skip to content
Snippets Groups Projects
Unverified Commit 75fac5f5 authored by bryanl's avatar bryanl
Browse files

Allow user to skip inclusion of default registries


Introduces a new init flag `--skip-default-registries` that skips adding
incubator to the intial list of available registries. This will allow
`ks` to work without access to GitHub.

Users can add additional registries at a later time with `ks registry
add`.

Fixes #204

Signed-off-by: default avatarbryanl <bryanliles@gmail.com>
parent bb346e6f
No related branches found
No related tags found
No related merge requests found
......@@ -74,6 +74,8 @@ const (
OptionServer = "server"
// OptionServerURI is serverURI option.
OptionServerURI = "server-uri"
// OptionSkipDefaultRegistries is skipDefaultRegistries option. Used by init.
OptionSkipDefaultRegistries = "skip-default-registries"
// OptionSkipGc is skipGc option.
OptionSkipGc = "skip-gc"
// OptionSpecFlag is specFlag option. Used for setting k8s spec.
......
......@@ -42,12 +42,13 @@ type initIncubatorFn func() (registry.Registry, error)
// Init creates a component namespace
type Init struct {
fs afero.Fs
name string
rootPath string
k8sSpecFlag string
serverURI string
namespace string
fs afero.Fs
name string
rootPath string
k8sSpecFlag string
serverURI string
namespace string
skipDefaultRegistries bool
appInitFn appInitFn
initIncubatorFn initIncubatorFn
......@@ -58,12 +59,13 @@ func NewInit(m map[string]interface{}) (*Init, error) {
ol := newOptionLoader(m)
i := &Init{
fs: ol.loadFs(OptionFs),
name: ol.loadString(OptionName),
rootPath: ol.loadString(OptionRootPath),
k8sSpecFlag: ol.loadString(OptionSpecFlag),
serverURI: ol.loadOptionalString(OptionServer),
namespace: ol.loadString(OptionNamespaceName),
fs: ol.loadFs(OptionFs),
name: ol.loadString(OptionName),
rootPath: ol.loadString(OptionRootPath),
k8sSpecFlag: ol.loadString(OptionSpecFlag),
serverURI: ol.loadOptionalString(OptionServer),
namespace: ol.loadString(OptionNamespaceName),
skipDefaultRegistries: ol.loadBool(OptionSkipDefaultRegistries),
appInitFn: appinit.Init,
initIncubatorFn: initIncubator,
......@@ -78,12 +80,16 @@ func NewInit(m map[string]interface{}) (*Init, error) {
// Run runs that ns create action.
func (i *Init) Run() error {
gh, err := i.initIncubatorFn()
if err != nil {
return err
}
var registries []registry.Registry
registries := []registry.Registry{gh}
if !i.skipDefaultRegistries {
gh, err := i.initIncubatorFn()
if err != nil {
return err
}
registries = append(registries, gh)
}
return i.appInitFn(
i.fs,
......
......@@ -35,45 +35,68 @@ func TestInit(t *testing.T) {
aServerURI := "http://example.com"
aNamespace := "my-namespace"
in := map[string]interface{}{
OptionFs: aFs,
OptionName: aName,
OptionRootPath: aRootPath,
OptionSpecFlag: aK8sSpecFlag,
OptionServer: aServerURI,
OptionNamespaceName: aNamespace,
cases := []struct {
name string
skipRegistries bool
}{
{
name: "with registries",
},
{
name: "without registries",
skipRegistries: true,
},
}
a, err := NewInit(in)
require.NoError(t, err)
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
in := map[string]interface{}{
OptionFs: aFs,
OptionName: aName,
OptionRootPath: aRootPath,
OptionSpecFlag: aK8sSpecFlag,
OptionServer: aServerURI,
OptionNamespaceName: aNamespace,
OptionSkipDefaultRegistries: tc.skipRegistries,
}
a.appInitFn = func(fs afero.Fs, name, rootPath, k8sSpecFlag, serverURI, namespace string, registries []registry.Registry) error {
assert.Equal(t, aFs, fs)
assert.Equal(t, aName, name)
assert.Equal(t, aRootPath, rootPath)
assert.Equal(t, aK8sSpecFlag, k8sSpecFlag)
assert.Equal(t, aServerURI, serverURI)
assert.Equal(t, aNamespace, namespace)
a, err := NewInit(in)
require.NoError(t, err)
assert.Len(t, registries, 1)
r := registries[0]
a.appInitFn = func(fs afero.Fs, name, rootPath, k8sSpecFlag, serverURI, namespace string, registries []registry.Registry) error {
assert.Equal(t, aFs, fs)
assert.Equal(t, aName, name)
assert.Equal(t, aRootPath, rootPath)
assert.Equal(t, aK8sSpecFlag, k8sSpecFlag)
assert.Equal(t, aServerURI, serverURI)
assert.Equal(t, aNamespace, namespace)
assert.Equal(t, "github", r.Protocol())
assert.Equal(t, "github.com/ksonnet/parts/tree/master/incubator", r.URI())
assert.Equal(t, "incubator", r.Name())
if !tc.skipRegistries {
assert.Len(t, registries, 1)
r := registries[0]
return nil
}
assert.Equal(t, "github", r.Protocol())
assert.Equal(t, "github.com/ksonnet/parts/tree/master/incubator", r.URI())
assert.Equal(t, "incubator", r.Name())
} else {
assert.Empty(t, registries)
}
return nil
}
a.initIncubatorFn = func() (registry.Registry, error) {
r := &rmocks.Registry{}
r.On("Protocol").Return("github")
r.On("URI").Return("github.com/ksonnet/parts/tree/master/incubator")
r.On("Name").Return("incubator")
return r, nil
}
a.initIncubatorFn = func() (registry.Registry, error) {
r := &rmocks.Registry{}
r.On("Protocol").Return("github")
r.On("URI").Return("github.com/ksonnet/parts/tree/master/incubator")
r.On("Name").Return("incubator")
return r, nil
err = a.Run()
require.NoError(t, err)
})
}
err = a.Run()
require.NoError(t, err)
})
}
......@@ -18,18 +18,29 @@ package cmd
const (
// For use in the commands (e.g., diff, apply, delete) that require either an
// environment or the -f flag.
flagComponent = "component"
flagCreate = "create"
flagDryRun = "dry-run"
flagEnv = "env"
flagFilename = "filename"
flagGcTag = "gc-tag"
flagIndex = "index"
flagNamespace = "namespace"
flagSkipGc = "skip-gc"
flagOutput = "output"
flagOverride = "override"
flagVersion = "version"
flagAPISpec = "api-spec"
flagComponent = "component"
flagCreate = "create"
flagDir = "dir"
flagDryRun = "dry-run"
flagEnv = "env"
flagExtVar = "ext-str"
flagExtVarFile = "ext-str-file"
flagFilename = "filename"
flagGcTag = "gc-tag"
flagIndex = "index"
flagJpath = "jpath"
flagNamespace = "namespace"
flagResolver = "resolve-images"
flagResolvFail = "resolve-images-error"
flagSkipDefaultRegistries = "skip-default-registries"
flagSkipGc = "skip-gc"
flagTlaVar = "tla-str"
flagTlaVarFile = "tla-str-file"
flagOutput = "output"
flagOverride = "override"
flagVerbose = "verbose"
flagVersion = "version"
shortComponent = "c"
shortFilename = "f"
......
......@@ -21,14 +21,19 @@ import (
"os"
"path/filepath"
"github.com/spf13/viper"
"github.com/ksonnet/ksonnet/actions"
"github.com/ksonnet/ksonnet/client"
"github.com/spf13/cobra"
)
const (
flagInitDir = "dir"
initShortDesc = "Initialize a ksonnet application"
vInitAPISpec = "init-api-spec"
vInitDir = "init-dir"
vInitSkipDefaultRegistries = "init-skip-default-registries"
)
var (
......@@ -37,13 +42,19 @@ var (
func init() {
RootCmd.AddCommand(initCmd)
initClientConfig = client.NewDefaultClientConfig()
initClientConfig.BindClientGoFlags(initCmd)
initCmd.Flags().String(flagDir, "", "Ksonnet application directory")
viper.BindPFlag(vInitDir, initCmd.Flag(flagDir))
// TODO: We need to make this default to checking the `kubeconfig` file.
initCmd.PersistentFlags().String(flagAPISpec, "",
initCmd.Flags().String(flagAPISpec, "",
"Manually specified Kubernetes API version. The corresponding OpenAPI spec is used to generate ksonnet's Kubernetes libraries")
viper.BindPFlag(vInitAPISpec, initCmd.Flag(flagAPISpec))
initClientConfig = client.NewDefaultClientConfig()
initClientConfig.BindClientGoFlags(initCmd)
initCmd.Flags().String(flagInitDir, "", "Ksonnet application directory")
initCmd.Flags().Bool(flagSkipDefaultRegistries, false, "Skip configuration of default registries")
viper.BindPFlag(vInitSkipDefaultRegistries, initCmd.Flag(flagSkipDefaultRegistries))
}
var initCmd = &cobra.Command{
......@@ -61,10 +72,7 @@ var initCmd = &cobra.Command{
return err
}
initDir, err := flags.GetString(flagInitDir)
if err != nil {
return err
}
initDir := viper.GetString(vInitDir)
appRoot, err := genKsRoot(appName, wd, initDir)
if err != nil {
......@@ -76,21 +84,19 @@ var initCmd = &cobra.Command{
return err
}
specFlag, err := flags.GetString(flagAPISpec)
if err != nil {
return err
}
specFlag := viper.GetString(vInitAPISpec)
if specFlag == "" {
specFlag = initClientConfig.GetAPISpec(server)
}
m := map[string]interface{}{
actions.OptionFs: appFs,
actions.OptionName: appName,
actions.OptionRootPath: appRoot,
actions.OptionSpecFlag: specFlag,
actions.OptionServer: server,
actions.OptionNamespaceName: namespace,
actions.OptionFs: appFs,
actions.OptionName: appName,
actions.OptionRootPath: appRoot,
actions.OptionSpecFlag: specFlag,
actions.OptionServer: server,
actions.OptionNamespaceName: namespace,
actions.OptionSkipDefaultRegistries: viper.GetBool(vInitSkipDefaultRegistries),
}
return runAction(actionInit, m)
......
......@@ -36,12 +36,13 @@ func Test_initCmd(t *testing.T) {
args: []string{"init", "app", "--namespace", "new-namespace", "--server", "http://127.0.0.1"},
action: actionInit,
expected: map[string]interface{}{
actions.OptionFs: appFs,
actions.OptionName: "app",
actions.OptionRootPath: root,
actions.OptionServer: "http://127.0.0.1",
actions.OptionSpecFlag: "version:v1.7.0",
actions.OptionNamespaceName: "new-namespace",
actions.OptionFs: appFs,
actions.OptionName: "app",
actions.OptionRootPath: root,
actions.OptionServer: "http://127.0.0.1",
actions.OptionSpecFlag: "version:v1.7.0",
actions.OptionNamespaceName: "new-namespace",
actions.OptionSkipDefaultRegistries: false,
},
},
}
......
......@@ -45,18 +45,6 @@ import (
_ "k8s.io/client-go/plugin/pkg/client/auth"
)
const (
flagVerbose = "verbose"
flagJpath = "jpath"
flagExtVar = "ext-str"
flagExtVarFile = "ext-str-file"
flagTlaVar = "tla-str"
flagTlaVarFile = "tla-str-file"
flagResolver = "resolve-images"
flagResolvFail = "resolve-images-error"
flagAPISpec = "api-spec"
)
var (
appFs = afero.NewOsFs()
ka app.App
......
......@@ -97,6 +97,7 @@ ks init app-name --dir=custom-location
--password string Password for basic authentication to the API server
--request-timeout string The length of time to wait before giving up on a single server request. Non-zero values should contain a corresponding time unit (e.g. 1s, 2m, 3h). A value of zero means don't timeout requests. (default "0")
--server string The address and port of the Kubernetes API server
--skip-default-registries Skip configuration of default registries
--token string Bearer token for authentication to the API server
--user string The name of the kubeconfig user to use
--username string Username for basic authentication to the API server
......
......@@ -162,9 +162,10 @@ func (e *e2e) initApp(options *initOptions) app {
}
type initOptions struct {
server string
context string
namespace string
server string
context string
namespace string
skipRegistries bool
}
func (o *initOptions) toSlice() ([]string, error) {
......@@ -187,5 +188,9 @@ func (o *initOptions) toSlice() ([]string, error) {
options = append(options, "--namespace", o.namespace)
}
if o.skipRegistries {
options = append(options, "--skip-default-registries")
}
return options, nil
}
// +build e2e
package e2e
import (
"path/filepath"
. "github.com/onsi/ginkgo"
)
var _ = Describe("ks init", func() {
var a app
var opts = &initOptions{}
JustBeforeEach(func() {
a = e.initApp(opts)
})
Context("in general", func() {
It("doesn't generate default registries", func() {
o := a.registryList()
assertOutput(filepath.Join("init", "registry-output.txt"), o.stdout)
})
})
Context("without default registries", func() {
BeforeEach(func() {
opts.skipRegistries = true
})
It("doesn't generate default registries", func() {
o := a.registryList()
assertOutput(filepath.Join("init", "skip-registry-output.txt"), o.stdout)
})
})
})
NAME OVERRIDE PROTOCOL URI
==== ======== ======== ===
incubator github github.com/ksonnet/parts/tree/master/incubator
NAME OVERRIDE PROTOCOL URI
==== ======== ======== ===
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment