mirror of https://github.com/knative/client.git
Allow configuration sink prefixes (#676)
This commit is contained in:
parent
82381f36e4
commit
d14c01fb5d
|
|
@ -20,6 +20,10 @@
|
||||||
|===
|
|===
|
||||||
| | Description | PR
|
| | Description | PR
|
||||||
|
|
||||||
|
| 🧽
|
||||||
|
| Allow configuration sink prefixes
|
||||||
|
| https://github.com/knative/client/pull/571[#571]
|
||||||
|
|
||||||
| 🧽
|
| 🧽
|
||||||
| Support multiple revisions on `kn revision delete`
|
| Support multiple revisions on `kn revision delete`
|
||||||
| https://github.com/knative/client/pull/657[#657]
|
| https://github.com/knative/client/pull/657[#657]
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ You'll need a `kubectl`-style config file to connect to your cluster.
|
||||||
|
|
||||||
## Kn Config
|
## Kn Config
|
||||||
|
|
||||||
There are a set of configuration parameters you can setup to better customize `kn`. In particular, you can specify where your `kn` plugins are located and how they are found. The `kn` configuration file is meant to capture these configuration options. Let's explore this file's location, and the options you are able to change with it.
|
There are a set of configuration parameters you can setup to better customize `kn`. For example, you can specify where your `kn` plugins are located and how they are found, and you can specify the prefix for your addressable `sink` objects. The `kn` configuration file is meant to capture these configuration options. Let's explore this file's location, and the options you are able to change with it.
|
||||||
|
|
||||||
### Location
|
### Location
|
||||||
|
|
||||||
|
|
@ -46,18 +46,30 @@ The default location `kn` looks for config is under the home directory of the us
|
||||||
|
|
||||||
### Options
|
### Options
|
||||||
|
|
||||||
There are two options you can specify in the `kn` config file and they are related to how `kn` locates plugins.
|
Below are the options you can specify in the `kn` config file.
|
||||||
|
|
||||||
1. `pluginsDir` which is the same as the persistent flag `--plugins-dir` and specifies the kn plugins directory. It defaults to: `~/.kn/plugins`. By using the persistent flag (when you issue a command) or by specifying the value in the `kn` config, a user can select which directory to find `kn` plugins. It can be any directory that is visible to the user.
|
1. `pluginsDir` which is the same as the persistent flag `--plugins-dir` and specifies the kn plugins directory. It defaults to: `~/.kn/plugins`. By using the persistent flag (when you issue a command) or by specifying the value in the `kn` config, a user can select which directory to find `kn` plugins. It can be any directory that is visible to the user.
|
||||||
|
|
||||||
2. `lookupPluginsInPath` which is the same as the persistent flag `--lookup-plugins-in-path` and specficies if `kn` should look for plugins anywhere in the specified `PATH` environment variable. This is a boolean configuration option and the default value is `false`.
|
2. `lookupPluginsInPath` which is the same as the persistent flag `--lookup-plugins-in-path` and specficies if `kn` should look for plugins anywhere in the specified `PATH` environment variable. This is a boolean configuration option and the default value is `false`.
|
||||||
|
|
||||||
|
3. `sink` defines your prefix to refer to Kubernetes addressable resources. To configure a sink prefix, define following in the config file:
|
||||||
|
1. `prefix`: Prefix you want to describe your sink as. `service` or `svc` (`serving.knative.dev/v1`) and `broker` (`eventing.knative.dev/v1alpha1`) are predefined prefixes in `kn`. These predefined prefixes can be overridden by values in configuration file.
|
||||||
|
2. `group`: The APIGroup of Kubernetes resource.
|
||||||
|
3. `version`: The version of Kubernetes resources.
|
||||||
|
4. `resource`: The plural name of Kubernetes resources (for example: services).
|
||||||
|
|
||||||
For example, the following `kn` config will look for `kn` plugins in the user's `PATH` and also execute plugin in `~/.kn/plugins`.
|
For example, the following `kn` config will look for `kn` plugins in the user's `PATH` and also execute plugin in `~/.kn/plugins`.
|
||||||
|
It also defines a sink prefix `myprefix` which refers to `brokers` in `eventing.knative.dev/v1alpha1`. With this configuration, you can use `myprefix:default` to describe a Broker `default` in `kn` command line.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cat ~/.kn/config.yaml
|
cat ~/.kn/config.yaml
|
||||||
lookupPluginsInPath: true
|
lookupPluginsInPath: true
|
||||||
pluginsdir: ~/.kn/plugins
|
pluginsdir: ~/.kn/plugins
|
||||||
|
sink:
|
||||||
|
- prefix: myprefix
|
||||||
|
group: eventing.knative.dev
|
||||||
|
version: v1alpha1
|
||||||
|
resource: brokers
|
||||||
```
|
```
|
||||||
----------------------------------------------------------
|
----------------------------------------------------------
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ import (
|
||||||
duckv1 "knative.dev/pkg/apis/duck/v1"
|
duckv1 "knative.dev/pkg/apis/duck/v1"
|
||||||
|
|
||||||
clientdynamic "knative.dev/client/pkg/dynamic"
|
clientdynamic "knative.dev/client/pkg/dynamic"
|
||||||
|
"knative.dev/client/pkg/kn/commands"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SinkFlags struct {
|
type SinkFlags struct {
|
||||||
|
|
@ -55,6 +56,17 @@ var SinkPrefixes = map[string]schema.GroupVersionResource{
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ConfigSinkPrefixes(prefixes []commands.SinkPrefixConfig) {
|
||||||
|
for _, p := range prefixes {
|
||||||
|
//user configration might override the default configuration
|
||||||
|
SinkPrefixes[p.Prefix] = schema.GroupVersionResource{
|
||||||
|
Resource: p.Resource,
|
||||||
|
Group: p.Group,
|
||||||
|
Version: p.Version,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ResolveSink returns the Destination referred to by the flags in the acceptor.
|
// ResolveSink returns the Destination referred to by the flags in the acceptor.
|
||||||
// It validates that any object the user is referring to exists.
|
// It validates that any object the user is referring to exists.
|
||||||
func (i *SinkFlags) ResolveSink(knclient clientdynamic.KnDynamicClient, namespace string) (*duckv1.Destination, error) {
|
func (i *SinkFlags) ResolveSink(knclient clientdynamic.KnDynamicClient, namespace string) (*duckv1.Destination, error) {
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,15 @@ var Cfg Config = Config{
|
||||||
type Config struct {
|
type Config struct {
|
||||||
PluginsDir string
|
PluginsDir string
|
||||||
LookupPlugins *bool
|
LookupPlugins *bool
|
||||||
|
SinkPrefixes []SinkPrefixConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
// SinkPrefixConfig is the struct of sink prefix config in kn config
|
||||||
|
type SinkPrefixConfig struct {
|
||||||
|
Prefix string
|
||||||
|
Resource string
|
||||||
|
Group string
|
||||||
|
Version string
|
||||||
}
|
}
|
||||||
|
|
||||||
// KnParams for creating commands. Useful for inserting mocks for testing.
|
// KnParams for creating commands. Useful for inserting mocks for testing.
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ import (
|
||||||
_ "k8s.io/client-go/plugin/pkg/client/auth/oidc"
|
_ "k8s.io/client-go/plugin/pkg/client/auth/oidc"
|
||||||
"knative.dev/client/pkg/kn/commands"
|
"knative.dev/client/pkg/kn/commands"
|
||||||
"knative.dev/client/pkg/kn/commands/completion"
|
"knative.dev/client/pkg/kn/commands/completion"
|
||||||
|
cmdflags "knative.dev/client/pkg/kn/commands/flags"
|
||||||
"knative.dev/client/pkg/kn/commands/plugin"
|
"knative.dev/client/pkg/kn/commands/plugin"
|
||||||
"knative.dev/client/pkg/kn/commands/revision"
|
"knative.dev/client/pkg/kn/commands/revision"
|
||||||
"knative.dev/client/pkg/kn/commands/route"
|
"knative.dev/client/pkg/kn/commands/route"
|
||||||
|
|
@ -126,7 +127,10 @@ func NewKnCommand(params ...commands.KnParams) *cobra.Command {
|
||||||
SilenceErrors: true,
|
SilenceErrors: true,
|
||||||
|
|
||||||
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
||||||
initConfigFlags()
|
err := initConfigFlags()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
return flags.ReconcileBoolFlags(cmd.Flags())
|
return flags.ReconcileBoolFlags(cmd.Flags())
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
@ -225,7 +229,7 @@ func initConfig() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func initConfigFlags() {
|
func initConfigFlags() error {
|
||||||
if viper.IsSet("plugins-dir") {
|
if viper.IsSet("plugins-dir") {
|
||||||
commands.Cfg.PluginsDir = viper.GetString("plugins-dir")
|
commands.Cfg.PluginsDir = viper.GetString("plugins-dir")
|
||||||
}
|
}
|
||||||
|
|
@ -234,6 +238,18 @@ func initConfigFlags() {
|
||||||
var aBool bool
|
var aBool bool
|
||||||
aBool = viper.GetBool("lookup-plugins")
|
aBool = viper.GetBool("lookup-plugins")
|
||||||
commands.Cfg.LookupPlugins = &aBool
|
commands.Cfg.LookupPlugins = &aBool
|
||||||
|
|
||||||
|
// set the Cfg.SinkPrefixes from viper if sink is configured
|
||||||
|
if viper.IsSet("sink") {
|
||||||
|
err := viper.UnmarshalKey("sink", &commands.Cfg.SinkPrefixes)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to parse sink prefixes configuration in file %s because of %v",
|
||||||
|
viper.ConfigFileUsed(), err)
|
||||||
|
}
|
||||||
|
cmdflags.ConfigSinkPrefixes(commands.Cfg.SinkPrefixes)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractKnPluginFlags(args []string) (string, bool, error) {
|
func extractKnPluginFlags(args []string) (string, bool, error) {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,92 @@
|
||||||
|
// Copyright 2020 The Knative 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 im
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
// +build e2e
|
||||||
|
|
||||||
|
package e2e
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"gotest.tools/assert"
|
||||||
|
"knative.dev/client/pkg/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
KnConfigContent string = `sink:
|
||||||
|
- group: serving.knative.dev
|
||||||
|
prefix: hello
|
||||||
|
resource: services
|
||||||
|
version: v1`
|
||||||
|
)
|
||||||
|
|
||||||
|
type sinkprefixTestConfig struct {
|
||||||
|
knConfigDir string
|
||||||
|
knConfigPath string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tc *sinkprefixTestConfig) setup() error {
|
||||||
|
var err error
|
||||||
|
tc.knConfigDir, err = ioutil.TempDir("", "kn1-config")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
tc.knConfigPath, err = createPluginFile("config.yaml", KnConfigContent, tc.knConfigDir, FileModeReadWrite)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tc *sinkprefixTestConfig) teardown() {
|
||||||
|
os.RemoveAll(tc.knConfigDir)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSinkPrefixConfig(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
test, err := NewE2eTest()
|
||||||
|
assert.NilError(t, err)
|
||||||
|
defer func() {
|
||||||
|
assert.NilError(t, test.Teardown())
|
||||||
|
}()
|
||||||
|
|
||||||
|
r := NewKnRunResultCollector(t)
|
||||||
|
defer r.DumpIfFailed()
|
||||||
|
|
||||||
|
tc := sinkprefixTestConfig{}
|
||||||
|
assert.NilError(t, tc.setup())
|
||||||
|
defer tc.teardown()
|
||||||
|
|
||||||
|
t.Log("Creating a testservice")
|
||||||
|
test.serviceCreate(t, r, "testsvc0")
|
||||||
|
t.Log("create cronJob sources with a sink to hello:testsvc0")
|
||||||
|
test.cronJobSourceCreateWithConfig(t, r, "testcronjobsource0", "* * * * */1", "ping", "hello:testsvc0", tc.knConfigPath)
|
||||||
|
|
||||||
|
jpSinkRefNameInSpec := "jsonpath={.spec.sink.ref.name}"
|
||||||
|
out, err := test.getResourceFieldsWithJSONPath("cronjobsource", "testcronjobsource0", jpSinkRefNameInSpec)
|
||||||
|
assert.NilError(t, err)
|
||||||
|
assert.Equal(t, out, "testsvc0")
|
||||||
|
|
||||||
|
t.Log("delete cronJob sources")
|
||||||
|
test.cronJobSourceDelete(t, r, "testcronjobsource0")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (test *e2eTest) cronJobSourceCreateWithConfig(t *testing.T, r *KnRunResultCollector, sourceName string, schedule string, data string, sink string, config string) {
|
||||||
|
out := test.kn.Run("source", "cronjob", "create", sourceName,
|
||||||
|
"--schedule", schedule, "--data", data, "--sink", sink, "--config", config)
|
||||||
|
assert.Check(t, util.ContainsAllIgnoreCase(out.Stdout, "cronjob", "source", sourceName, "created", "namespace", test.kn.namespace))
|
||||||
|
r.AssertNoError(out)
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue