Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow configuration sink prefixes #676

Merged
merged 1 commit into from
Feb 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@
|===
| | Description | PR

| 🧽
| Allow configuration sink prefixes
| https://github.com/knative/client/pull/571[#571]

| 🧽
| Support multiple revisions on `kn revision delete`
| https://github.com/knative/client/pull/657[#657]
Expand Down
16 changes: 14 additions & 2 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,26 +38,38 @@ You'll need a `kubectl`-style config file to connect to your cluster.

## 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

The default location `kn` looks for config is under the home directory of the user at `$HOME/.kn/config.yaml`. It is not created for you as part of the `kn` installation. You can create this file elsewhere and use the `--config` flag to specify its path.

### 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.

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`.
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
cat ~/.kn/config.yaml
lookupPluginsInPath: true
pluginsdir: ~/.kn/plugins
sink:
- prefix: myprefix
group: eventing.knative.dev
version: v1alpha1
resource: brokers
```
----------------------------------------------------------

Expand Down
12 changes: 12 additions & 0 deletions pkg/kn/commands/flags/sink.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
duckv1 "knative.dev/pkg/apis/duck/v1"

clientdynamic "knative.dev/client/pkg/dynamic"
"knative.dev/client/pkg/kn/commands"
)

type SinkFlags struct {
Expand Down Expand Up @@ -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.
// It validates that any object the user is referring to exists.
func (i *SinkFlags) ResolveSink(knclient clientdynamic.KnDynamicClient, namespace string) (*duckv1.Destination, error) {
Expand Down
9 changes: 9 additions & 0 deletions pkg/kn/commands/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,15 @@ var Cfg Config = Config{
type Config struct {
PluginsDir string
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.
Expand Down
20 changes: 18 additions & 2 deletions pkg/kn/core/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
_ "k8s.io/client-go/plugin/pkg/client/auth/oidc"
"knative.dev/client/pkg/kn/commands"
"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/revision"
"knative.dev/client/pkg/kn/commands/route"
Expand Down Expand Up @@ -126,7 +127,10 @@ func NewKnCommand(params ...commands.KnParams) *cobra.Command {
SilenceErrors: true,

PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
initConfigFlags()
err := initConfigFlags()
if err != nil {
return err
}
return flags.ReconcileBoolFlags(cmd.Flags())
},
}
Expand Down Expand Up @@ -225,7 +229,7 @@ func initConfig() {
}
}

func initConfigFlags() {
func initConfigFlags() error {
if viper.IsSet("plugins-dir") {
commands.Cfg.PluginsDir = viper.GetString("plugins-dir")
}
Expand All @@ -234,6 +238,18 @@ func initConfigFlags() {
var aBool bool
aBool = viper.GetBool("lookup-plugins")
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) {
Expand Down
92 changes: 92 additions & 0 deletions test/e2e/sinkprefix_test.go
Original file line number Diff line number Diff line change
@@ -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) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since CronJob source is deprecated and will be removed, I'd defer to use it for any new work/tests. As we'll need to re-work this later. Fine for now, but for any subsequent tests, lets use other sources.

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)
}