From af61ff8f24c0181bab43376e2a74280592bbac86 Mon Sep 17 00:00:00 2001 From: Navid Shaikh Date: Sun, 15 Dec 2019 15:50:20 +0530 Subject: [PATCH 01/16] Dont return created ApiServer source object but only error - After ApiServer source object is created, we don't need it to pass around in caller function. --- docs/cmd/kn_source_apiserver_create.md | 2 +- pkg/eventing/sources/v1alpha1/apiserver_client.go | 11 ++++++----- .../sources/v1alpha1/apiserver_client_test.go | 12 ++++-------- pkg/kn/commands/source/apiserver/create.go | 4 ++-- 4 files changed, 13 insertions(+), 16 deletions(-) diff --git a/docs/cmd/kn_source_apiserver_create.md b/docs/cmd/kn_source_apiserver_create.md index 0ddc5e5b66..5fdffa990d 100644 --- a/docs/cmd/kn_source_apiserver_create.md +++ b/docs/cmd/kn_source_apiserver_create.md @@ -13,7 +13,7 @@ kn source apiserver create NAME --resource RESOURCE --service-account ACCOUNTNAM ### Examples ``` - + # Create an ApiServerSource 'k8sevents' which consumes Kubernetes events and sends message to service 'mysvc' as a cloudevent kn source apiserver create k8sevents --resource Event --service-account myaccountname --sink svc:mysvc ``` diff --git a/pkg/eventing/sources/v1alpha1/apiserver_client.go b/pkg/eventing/sources/v1alpha1/apiserver_client.go index 0a6b69d257..45725cba76 100644 --- a/pkg/eventing/sources/v1alpha1/apiserver_client.go +++ b/pkg/eventing/sources/v1alpha1/apiserver_client.go @@ -26,7 +26,7 @@ import ( type KnApiServerSourcesClient interface { // Get an ApiServerSource by object - CreateApiServerSource(apisvrsrc *v1alpha1.ApiServerSource) (*v1alpha1.ApiServerSource, error) + CreateApiServerSource(apisvrsrc *v1alpha1.ApiServerSource) error // Delete an ApiServerSource by name DeleteApiServerSource(name string) error @@ -52,12 +52,13 @@ func newKnApiServerSourcesClient(client client_v1alpha1.ApiServerSourceInterface } //CreateApiServerSource is used to create an instance of ApiServerSource -func (c *apiServerSourcesClient) CreateApiServerSource(apisvrsrc *v1alpha1.ApiServerSource) (*v1alpha1.ApiServerSource, error) { - ins, err := c.client.Create(apisvrsrc) +func (c *apiServerSourcesClient) CreateApiServerSource(apisvrsrc *v1alpha1.ApiServerSource) error { + _, err := c.client.Create(apisvrsrc) if err != nil { - return nil, kn_errors.GetError(err) + return kn_errors.GetError(err) } - return ins, nil + + return nil } //DeleteApiServerSource is used to create an instance of ApiServerSource diff --git a/pkg/eventing/sources/v1alpha1/apiserver_client_test.go b/pkg/eventing/sources/v1alpha1/apiserver_client_test.go index 225f61ae98..ce95e32cfa 100644 --- a/pkg/eventing/sources/v1alpha1/apiserver_client_test.go +++ b/pkg/eventing/sources/v1alpha1/apiserver_client_test.go @@ -53,14 +53,12 @@ func TestDeleteApiServerSource(t *testing.T) { }) t.Run("create apiserversource without error", func(t *testing.T) { - ins, err := client.CreateApiServerSource(apisourceNew) + err := client.CreateApiServerSource(apisourceNew) assert.NilError(t, err) - assert.Equal(t, ins.Name, srcName) - assert.Equal(t, ins.Namespace, testApiServerSourceNamespace) }) t.Run("create apiserversource with an error returns an error object", func(t *testing.T) { - _, err := client.CreateApiServerSource(newApiServerSource("unknown")) + err := client.CreateApiServerSource(newApiServerSource("unknown")) assert.ErrorContains(t, err, "unknown") }) } @@ -83,14 +81,12 @@ func TestCreateApiServerSource(t *testing.T) { }) t.Run("create apiserversource without error", func(t *testing.T) { - ins, err := client.CreateApiServerSource(apisourceNew) + err := client.CreateApiServerSource(apisourceNew) assert.NilError(t, err) - assert.Equal(t, ins.Name, srcName) - assert.Equal(t, ins.Namespace, testApiServerSourceNamespace) }) t.Run("create apiserversource with an error returns an error object", func(t *testing.T) { - _, err := client.CreateApiServerSource(newApiServerSource("unknown")) + err := client.CreateApiServerSource(newApiServerSource("unknown")) assert.ErrorContains(t, err, "unknown") }) } diff --git a/pkg/kn/commands/source/apiserver/create.go b/pkg/kn/commands/source/apiserver/create.go index dc7be52cc9..3c88fb42d9 100644 --- a/pkg/kn/commands/source/apiserver/create.go +++ b/pkg/kn/commands/source/apiserver/create.go @@ -33,7 +33,7 @@ func NewApiServerCreateCommand(p *commands.KnParams) *cobra.Command { cmd := &cobra.Command{ Use: "create NAME --resource RESOURCE --service-account ACCOUNTNAME --sink SINK --mode MODE", Short: "Create an ApiServerSource, which watches for Kubernetes events and forwards them to a sink", - Example: ` + Example: ` # Create an ApiServerSource 'k8sevents' which consumes Kubernetes events and sends message to service 'mysvc' as a cloudevent kn source apiserver create k8sevents --resource Event --service-account myaccountname --sink svc:mysvc`, @@ -73,7 +73,7 @@ func NewApiServerCreateCommand(p *commands.KnParams) *cobra.Command { apisrvsrc.Spec.Sink = objectRef // create - _, err = sourcesClient.ApiServerSourcesClient().CreateApiServerSource(apisrvsrc) + err = sourcesClient.ApiServerSourcesClient().CreateApiServerSource(apisrvsrc) if err != nil { return fmt.Errorf( "cannot create ApiServerSource '%s' in namespace '%s' "+ From f6a15d19e0e0ea5144a506a83f4061b2b3c54153 Mon Sep 17 00:00:00 2001 From: Navid Shaikh Date: Sun, 15 Dec 2019 16:54:11 +0530 Subject: [PATCH 02/16] Align creating ApiServer source client, removes unit tests --- pkg/kn/commands/source/apiserver/apiserver.go | 41 ++++++- pkg/kn/commands/source/apiserver/create.go | 4 +- .../commands/source/apiserver/create_test.go | 102 ------------------ pkg/kn/commands/source/apiserver/delete.go | 4 +- .../commands/source/apiserver/delete_test.go | 61 ----------- 5 files changed, 41 insertions(+), 171 deletions(-) delete mode 100644 pkg/kn/commands/source/apiserver/create_test.go delete mode 100644 pkg/kn/commands/source/apiserver/delete_test.go diff --git a/pkg/kn/commands/source/apiserver/apiserver.go b/pkg/kn/commands/source/apiserver/apiserver.go index 3eaffc1c59..89336c5504 100644 --- a/pkg/kn/commands/source/apiserver/apiserver.go +++ b/pkg/kn/commands/source/apiserver/apiserver.go @@ -16,16 +16,49 @@ package apiserver import ( "github.com/spf13/cobra" + "k8s.io/client-go/tools/clientcmd" + sources_v1alpha1 "knative.dev/eventing/pkg/client/clientset/versioned/typed/sources/v1alpha1" + + "knative.dev/client/pkg/eventing/sources/v1alpha1" "knative.dev/client/pkg/kn/commands" ) func NewApiServerCommand(p *commands.KnParams) *cobra.Command { - apiServerImporterCmd := &cobra.Command{ + apiServerSourceCmd := &cobra.Command{ Use: "apiserver", Short: "Kubernetes API Server Event Source command group", } - apiServerImporterCmd.AddCommand(NewApiServerCreateCommand(p)) - apiServerImporterCmd.AddCommand(NewApiServerDeleteCommand(p)) - return apiServerImporterCmd + apiServerSourceCmd.AddCommand(NewApiServerCreateCommand(p)) + apiServerSourceCmd.AddCommand(NewApiServerDeleteCommand(p)) + return apiServerSourceCmd +} + +var apiServerSourceClientFactory func(config clientcmd.ClientConfig, namespace string) (v1alpha1.KnApiServerSourcesClient, error) + +func newApiServerSourceClient(p *commands.KnParams, cmd *cobra.Command) (v1alpha1.KnApiServerSourcesClient, error) { + namespace, err := p.GetNamespace(cmd) + if err != nil { + return nil, err + } + + if apiServerSourceClientFactory != nil { + config, err := p.GetClientConfig() + if err != nil { + return nil, err + } + return apiServerSourceClientFactory(config, namespace) + } + + clientConfig, err := p.RestConfig() + if err != nil { + return nil, err + } + + client, err := sources_v1alpha1.NewForConfig(clientConfig) + if err != nil { + return nil, err + } + + return v1alpha1.NewKnSourcesClient(client, namespace).ApiServerSourcesClient(), nil } diff --git a/pkg/kn/commands/source/apiserver/create.go b/pkg/kn/commands/source/apiserver/create.go index 3c88fb42d9..35a3ccd5a2 100644 --- a/pkg/kn/commands/source/apiserver/create.go +++ b/pkg/kn/commands/source/apiserver/create.go @@ -50,7 +50,7 @@ func NewApiServerCreateCommand(p *commands.KnParams) *cobra.Command { } // get client - sourcesClient, err := p.NewSourcesClient(namespace) + apiSourceClient, err := newApiServerSourceClient(p, cmd) if err != nil { return err } @@ -73,7 +73,7 @@ func NewApiServerCreateCommand(p *commands.KnParams) *cobra.Command { apisrvsrc.Spec.Sink = objectRef // create - err = sourcesClient.ApiServerSourcesClient().CreateApiServerSource(apisrvsrc) + err = apiSourceClient.CreateApiServerSource(apisrvsrc) if err != nil { return fmt.Errorf( "cannot create ApiServerSource '%s' in namespace '%s' "+ diff --git a/pkg/kn/commands/source/apiserver/create_test.go b/pkg/kn/commands/source/apiserver/create_test.go deleted file mode 100644 index eabda0817f..0000000000 --- a/pkg/kn/commands/source/apiserver/create_test.go +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright © 2019 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 implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package apiserver - -import ( - "errors" - "fmt" - "testing" - - "gotest.tools/assert" - v1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - client_testing "k8s.io/client-go/testing" - "knative.dev/client/pkg/kn/commands" - "knative.dev/client/pkg/util" - "knative.dev/eventing/pkg/apis/sources/v1alpha1" - duckv1beta1 "knative.dev/pkg/apis/duck/v1beta1" -) - -var ( - testApiServerSrcName = "foo" -) - -func fakeApiServerSourceCreate(args []string, withExistingService bool, sync bool) ( - action client_testing.Action, - src *v1alpha1.ApiServerSource, - output string, - err error) { - knParams := &commands.KnParams{} - cmd, fakeSource, buf := commands.CreateSourcesTestKnCommand(NewApiServerCommand(knParams), knParams) - fakeSource.AddReactor("create", "apiserversources", - func(a client_testing.Action) (bool, runtime.Object, error) { - createAction, ok := a.(client_testing.CreateAction) - action = createAction - if !ok { - return true, nil, fmt.Errorf("wrong kind of action %v", a) - } - src, ok = createAction.GetObject().(*v1alpha1.ApiServerSource) - if !ok { - return true, nil, errors.New("was passed the wrong object") - } - return true, src, nil - }) - cmd.SetArgs(args) - err = cmd.Execute() - if err != nil { - output = err.Error() - return - } - output = buf.String() - return -} - -func TestApiServerSourceCreate(t *testing.T) { - action, created, output, err := fakeApiServerSourceCreate([]string{ - "apiserver", "create", testApiServerSrcName, "--resource", "Event:v1:true", "--service-account", "myaccountname", "--sink", "svc:mysvc"}, true, false) - if err != nil { - t.Fatal(err) - } else if !action.Matches("create", "apiserversources") { - t.Fatalf("Bad action %v", action) - } - - //construct a wanted instance - wanted := &v1alpha1.ApiServerSource{ - ObjectMeta: metav1.ObjectMeta{ - Name: testApiServerSrcName, - Namespace: commands.FakeNamespace, - }, - Spec: v1alpha1.ApiServerSourceSpec{ - Resources: []v1alpha1.ApiServerResource{{ - APIVersion: "v1", - Kind: "Event", - Controller: true, - }}, - ServiceAccountName: "myaccountname", - Mode: "Ref", - Sink: &duckv1beta1.Destination{ - Ref: &v1.ObjectReference{ - Kind: "Service", - APIVersion: "serving.knative.dev/v1alpha1", - }, - }, - }, - } - - //assert equal - assert.DeepEqual(t, wanted, created) - assert.Check(t, util.ContainsAll(output, "ApiServerSource", testApiServerSrcName, "created", "namespace", commands.FakeNamespace)) -} diff --git a/pkg/kn/commands/source/apiserver/delete.go b/pkg/kn/commands/source/apiserver/delete.go index 9a6b59d547..27a65ccaa1 100644 --- a/pkg/kn/commands/source/apiserver/delete.go +++ b/pkg/kn/commands/source/apiserver/delete.go @@ -41,12 +41,12 @@ func NewApiServerDeleteCommand(p *commands.KnParams) *cobra.Command { return err } - sourcesClient, err := p.NewSourcesClient(namespace) + apiSourceClient, err := newApiServerSourceClient(p, cmd) if err != nil { return err } - err = sourcesClient.ApiServerSourcesClient().DeleteApiServerSource(name) + err = apiSourceClient.DeleteApiServerSource(name) if err != nil { return err } diff --git a/pkg/kn/commands/source/apiserver/delete_test.go b/pkg/kn/commands/source/apiserver/delete_test.go deleted file mode 100644 index 0b2603f389..0000000000 --- a/pkg/kn/commands/source/apiserver/delete_test.go +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright © 2019 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 implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package apiserver - -import ( - "testing" - - "gotest.tools/assert" - "k8s.io/apimachinery/pkg/runtime" - client_testing "k8s.io/client-go/testing" - "knative.dev/client/pkg/kn/commands" - "knative.dev/client/pkg/util" -) - -func fakeServiceDelete(args []string) (action client_testing.Action, name string, output string, err error) { - knParams := &commands.KnParams{} - cmd, fakeSource, buf := commands.CreateSourcesTestKnCommand(NewApiServerCommand(knParams), knParams) - fakeSource.AddReactor("delete", "apiserversources", - func(a client_testing.Action) (bool, runtime.Object, error) { - deleteAction, _ := a.(client_testing.DeleteAction) - action = deleteAction - name = deleteAction.GetName() - return true, nil, nil - }) - cmd.SetArgs(args) - err = cmd.Execute() - if err != nil { - return - } - output = buf.String() - return -} - -func TestServiceDelete(t *testing.T) { - srcName := "src-12345" - action, name, output, err := fakeServiceDelete([]string{"apiserver", "delete", srcName}) - if err != nil { - t.Error(err) - return - } - if action == nil { - t.Errorf("No action") - } else if !action.Matches("delete", "apiserversources") { - t.Errorf("Bad action %v", action) - } else if name != srcName { - t.Errorf("Bad service name returned after delete.") - } - assert.Check(t, util.ContainsAll(output, "ApiServerSource", srcName, "deleted", "namespace", commands.FakeNamespace)) -} From 571806718d9bdb70f9a2215d5ec7d1b99dc3f97f Mon Sep 17 00:00:00 2001 From: Navid Shaikh Date: Sun, 15 Dec 2019 17:24:45 +0530 Subject: [PATCH 03/16] Add ApiServer source update command --- docs/cmd/kn_source_apiserver.md | 1 + docs/cmd/kn_source_apiserver_create.md | 2 +- docs/cmd/kn_source_apiserver_update.md | 47 ++++++++++ .../sources/v1alpha1/apiserver_client.go | 38 ++++++-- pkg/kn/commands/source/apiserver/apiserver.go | 1 + .../apiserver/{create_flag.go => flags.go} | 25 ++++- pkg/kn/commands/source/apiserver/update.go | 93 +++++++++++++++++++ 7 files changed, 195 insertions(+), 12 deletions(-) create mode 100644 docs/cmd/kn_source_apiserver_update.md rename pkg/kn/commands/source/apiserver/{create_flag.go => flags.go} (80%) create mode 100644 pkg/kn/commands/source/apiserver/update.go diff --git a/docs/cmd/kn_source_apiserver.md b/docs/cmd/kn_source_apiserver.md index 0b9de677c8..5cfb43b7a8 100644 --- a/docs/cmd/kn_source_apiserver.md +++ b/docs/cmd/kn_source_apiserver.md @@ -29,4 +29,5 @@ kn source apiserver [flags] * [kn source](kn_source.md) - Event source command group * [kn source apiserver create](kn_source_apiserver_create.md) - Create an ApiServerSource, which watches for Kubernetes events and forwards them to a sink * [kn source apiserver delete](kn_source_apiserver_delete.md) - Delete an ApiServerSource. +* [kn source apiserver update](kn_source_apiserver_update.md) - update an ApiServerSource, which watches for Kubernetes events and forwards them to a sink diff --git a/docs/cmd/kn_source_apiserver_create.md b/docs/cmd/kn_source_apiserver_create.md index 5fdffa990d..e8a1cb7fcf 100644 --- a/docs/cmd/kn_source_apiserver_create.md +++ b/docs/cmd/kn_source_apiserver_create.md @@ -28,7 +28,7 @@ kn source apiserver create NAME --resource RESOURCE --service-account ACCOUNTNAM -n, --namespace string Specify the namespace to operate in. --resource strings Comma seperate Kind:APIVersion:isController list, e.g. Event:v1:true. "APIVersion" and "isControler" can be omitted. - "APIVersion" is "v1" by default, "isController" is "false" by default. + "APIVersion" is "v1" by default, "isController" is "false" by default. --service-account string Name of the service account to use to run this source -s, --sink string Addressable sink for events ``` diff --git a/docs/cmd/kn_source_apiserver_update.md b/docs/cmd/kn_source_apiserver_update.md new file mode 100644 index 0000000000..0779ec4b7e --- /dev/null +++ b/docs/cmd/kn_source_apiserver_update.md @@ -0,0 +1,47 @@ +## kn source apiserver update + +update an ApiServerSource, which watches for Kubernetes events and forwards them to a sink + +### Synopsis + +update an ApiServerSource, which watches for Kubernetes events and forwards them to a sink + +``` +kn source apiserver update NAME --resource RESOURCE --service-account ACCOUNTNAME --sink SINK --mode MODE [flags] +``` + +### Examples + +``` + + # Update an ApiServerSource 'k8sevents' with different service account and sink service + kn source apiserver update k8sevents --service-account newsa --sink svc:newsvc +``` + +### Options + +``` + -h, --help help for update + --mode string The mode the receive adapter controller runs under:, + "Ref" sends only the reference to the resource, + "Resource" send the full resource. (default "Ref") + -n, --namespace string Specify the namespace to operate in. + --resource strings Comma seperate Kind:APIVersion:isController list, e.g. Event:v1:true. + "APIVersion" and "isControler" can be omitted. + "APIVersion" is "v1" by default, "isController" is "false" by default. + --service-account string Name of the service account to use to run this source + -s, --sink string Addressable sink for events +``` + +### Options inherited from parent commands + +``` + --config string kn config file (default is $HOME/.kn/config.yaml) + --kubeconfig string kubectl config file (default is $HOME/.kube/config) + --log-http log http traffic +``` + +### SEE ALSO + +* [kn source apiserver](kn_source_apiserver.md) - Kubernetes API Server Event Source command group + diff --git a/pkg/eventing/sources/v1alpha1/apiserver_client.go b/pkg/eventing/sources/v1alpha1/apiserver_client.go index 45725cba76..aba7d43e27 100644 --- a/pkg/eventing/sources/v1alpha1/apiserver_client.go +++ b/pkg/eventing/sources/v1alpha1/apiserver_client.go @@ -15,7 +15,7 @@ package v1alpha1 import ( - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "knative.dev/eventing/pkg/apis/sources/v1alpha1" client_v1alpha1 "knative.dev/eventing/pkg/client/clientset/versioned/typed/sources/v1alpha1" @@ -25,8 +25,14 @@ import ( // Interface for working with ApiServer sources type KnApiServerSourcesClient interface { - // Get an ApiServerSource by object - CreateApiServerSource(apisvrsrc *v1alpha1.ApiServerSource) error + // Get an ApiServerSource by name + GetApiServerSource(name string) (*v1alpha1.ApiServerSource, error) + + // Create an ApiServerSource by object + CreateApiServerSource(apiSource *v1alpha1.ApiServerSource) error + + // Update an ApiServerSource by object + UpdateApiServerSource(apiSource *v1alpha1.ApiServerSource) error // Delete an ApiServerSource by name DeleteApiServerSource(name string) error @@ -51,9 +57,29 @@ func newKnApiServerSourcesClient(client client_v1alpha1.ApiServerSourceInterface } } +//GetApiServerSource returns apiSource object if present +func (c *apiServerSourcesClient) GetApiServerSource(name string) (*v1alpha1.ApiServerSource, error) { + apiSource, err := c.client.Get(name, metav1.GetOptions{}) + if err != nil { + return nil, kn_errors.GetError(err) + } + + return apiSource, nil +} + //CreateApiServerSource is used to create an instance of ApiServerSource -func (c *apiServerSourcesClient) CreateApiServerSource(apisvrsrc *v1alpha1.ApiServerSource) error { - _, err := c.client.Create(apisvrsrc) +func (c *apiServerSourcesClient) CreateApiServerSource(apiSource *v1alpha1.ApiServerSource) error { + _, err := c.client.Create(apiSource) + if err != nil { + return kn_errors.GetError(err) + } + + return nil +} + +//UpdateApiServerSource is used to update an instance of ApiServerSource +func (c *apiServerSourcesClient) UpdateApiServerSource(apiSource *v1alpha1.ApiServerSource) error { + _, err := c.client.Update(apiSource) if err != nil { return kn_errors.GetError(err) } @@ -63,7 +89,7 @@ func (c *apiServerSourcesClient) CreateApiServerSource(apisvrsrc *v1alpha1.ApiSe //DeleteApiServerSource is used to create an instance of ApiServerSource func (c *apiServerSourcesClient) DeleteApiServerSource(name string) error { - err := c.client.Delete(name, &v1.DeleteOptions{}) + err := c.client.Delete(name, &metav1.DeleteOptions{}) return err } diff --git a/pkg/kn/commands/source/apiserver/apiserver.go b/pkg/kn/commands/source/apiserver/apiserver.go index 89336c5504..75b181113b 100644 --- a/pkg/kn/commands/source/apiserver/apiserver.go +++ b/pkg/kn/commands/source/apiserver/apiserver.go @@ -30,6 +30,7 @@ func NewApiServerCommand(p *commands.KnParams) *cobra.Command { Short: "Kubernetes API Server Event Source command group", } apiServerSourceCmd.AddCommand(NewApiServerCreateCommand(p)) + apiServerSourceCmd.AddCommand(NewApiServerUpdateCommand(p)) apiServerSourceCmd.AddCommand(NewApiServerDeleteCommand(p)) return apiServerSourceCmd } diff --git a/pkg/kn/commands/source/apiserver/create_flag.go b/pkg/kn/commands/source/apiserver/flags.go similarity index 80% rename from pkg/kn/commands/source/apiserver/create_flag.go rename to pkg/kn/commands/source/apiserver/flags.go index b3048758d7..9224ea38e8 100644 --- a/pkg/kn/commands/source/apiserver/create_flag.go +++ b/pkg/kn/commands/source/apiserver/flags.go @@ -19,7 +19,7 @@ import ( "strings" "github.com/spf13/cobra" - sources_v1alpha1 "knative.dev/eventing/pkg/apis/sources/v1alpha1" + "knative.dev/eventing/pkg/apis/sources/v1alpha1" ) const ( @@ -35,11 +35,11 @@ type ApiServerSourceUpdateFlags struct { } // GetApiServerResourceArray is to return an array of ApiServerResource from a string. A sample is Event:v1:true,Pod:v2:false -func (f *ApiServerSourceUpdateFlags) GetApiServerResourceArray() []sources_v1alpha1.ApiServerResource { - var resourceList []sources_v1alpha1.ApiServerResource +func (f *ApiServerSourceUpdateFlags) GetApiServerResourceArray() []v1alpha1.ApiServerResource { + var resourceList []v1alpha1.ApiServerResource for _, r := range f.Resources { version, kind, controller := getValidResource(r) - resourceRef := sources_v1alpha1.ApiServerResource{ + resourceRef := v1alpha1.ApiServerResource{ APIVersion: version, Kind: kind, Controller: controller, @@ -85,5 +85,20 @@ func (f *ApiServerSourceUpdateFlags) Add(cmd *cobra.Command) { nil, `Comma seperate Kind:APIVersion:isController list, e.g. Event:v1:true. "APIVersion" and "isControler" can be omitted. -"APIVersion" is "v1" by default, "isController" is "false" by default. `) +"APIVersion" is "v1" by default, "isController" is "false" by default.`) +} + +//Apply updates the service object based on flags +func (f *ApiServerSourceUpdateFlags) Apply(source *v1alpha1.ApiServerSource, cmd *cobra.Command) { + if cmd.Flags().Changed("service-account") { + source.Spec.ServiceAccountName = f.ServiceAccountName + } + + if cmd.Flags().Changed("mod") { + source.Spec.Mode = f.Mode + } + + if cmd.Flags().Changed("resource") { + source.Spec.Resources = f.GetApiServerResourceArray() + } } diff --git a/pkg/kn/commands/source/apiserver/update.go b/pkg/kn/commands/source/apiserver/update.go new file mode 100644 index 0000000000..a5411eb82c --- /dev/null +++ b/pkg/kn/commands/source/apiserver/update.go @@ -0,0 +1,93 @@ +// Copyright © 2019 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 implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package apiserver + +import ( + "errors" + "fmt" + + "github.com/spf13/cobra" + + "knative.dev/client/pkg/kn/commands" + "knative.dev/client/pkg/kn/commands/flags" +) + +func NewApiServerUpdateCommand(p *commands.KnParams) *cobra.Command { + var apiServerUpdateFlags ApiServerSourceUpdateFlags + var sinkFlags flags.SinkFlags + + cmd := &cobra.Command{ + Use: "update NAME --resource RESOURCE --service-account ACCOUNTNAME --sink SINK --mode MODE", + Short: "update an ApiServerSource, which watches for Kubernetes events and forwards them to a sink", + Example: ` + # Update an ApiServerSource 'k8sevents' with different service account and sink service + kn source apiserver update k8sevents --service-account newsa --sink svc:newsvc`, + + RunE: func(cmd *cobra.Command, args []string) (err error) { + if len(args) != 1 { + return errors.New("requires the name of the source as single argument") + } + name := args[0] + + // get namespace + namespace, err := p.GetNamespace(cmd) + if err != nil { + return err + } + + // get client + sourcesClient, err := newApiServerSourceClient(p, cmd) + if err != nil { + return err + } + + source, err := sourcesClient.GetApiServerSource(name) + if err != nil { + return err + } + + // resolve sink + servingClient, err := p.NewServingClient(namespace) + if err != nil { + return err + } + + objectRef, err := sinkFlags.ResolveSink(servingClient) + if err != nil { + return fmt.Errorf( + "cannot update ApiServerSource '%s' in namespace '%s' "+ + "because %v", name, namespace, err) + } + + source = source.DeepCopy() + apiServerUpdateFlags.Apply(source, cmd) + source.Spec.Sink = objectRef + + err = sourcesClient.UpdateApiServerSource(source) + if err != nil { + return fmt.Errorf( + "cannot create ApiServerSource '%s' in namespace '%s' "+ + "because %s", name, namespace, err) + } + fmt.Fprintf(cmd.OutOrStdout(), "ApiServerSource '%s' updated in namespace '%s'.\n", args[0], namespace) + return nil + }, + } + commands.AddNamespaceFlags(cmd.Flags(), false) + apiServerUpdateFlags.Add(cmd) + sinkFlags.Add(cmd) + + return cmd +} From 31881ef89bee37a7f50ae0dce6015fc8f5f259da Mon Sep 17 00:00:00 2001 From: Navid Shaikh Date: Sun, 15 Dec 2019 17:33:10 +0530 Subject: [PATCH 04/16] Rename TestMockKnClient to TestMockKnCronJobSourceClient --- pkg/eventing/sources/v1alpha1/cronjob_client_mock_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/eventing/sources/v1alpha1/cronjob_client_mock_test.go b/pkg/eventing/sources/v1alpha1/cronjob_client_mock_test.go index 5e835c0ead..d2b54a5ff4 100644 --- a/pkg/eventing/sources/v1alpha1/cronjob_client_mock_test.go +++ b/pkg/eventing/sources/v1alpha1/cronjob_client_mock_test.go @@ -20,7 +20,7 @@ import ( "knative.dev/eventing/pkg/apis/sources/v1alpha1" ) -func TestMockKnClient(t *testing.T) { +func TestMockKnCronJobSourceClient(t *testing.T) { client := NewMockKnCronJobSourceClient(t) From 99b3952765c8e1e8aa701d7796bac82b9938f7d3 Mon Sep 17 00:00:00 2001 From: Navid Shaikh Date: Sun, 15 Dec 2019 17:33:42 +0530 Subject: [PATCH 05/16] Add mock client for ApiServer Source and its tests --- .../sources/v1alpha1/apiserver_client_mock.go | 108 ++++++++++++++++++ .../v1alpha1/apiserver_client_mock_test.go | 43 +++++++ 2 files changed, 151 insertions(+) create mode 100644 pkg/eventing/sources/v1alpha1/apiserver_client_mock.go create mode 100644 pkg/eventing/sources/v1alpha1/apiserver_client_mock_test.go diff --git a/pkg/eventing/sources/v1alpha1/apiserver_client_mock.go b/pkg/eventing/sources/v1alpha1/apiserver_client_mock.go new file mode 100644 index 0000000000..be0d9153cc --- /dev/null +++ b/pkg/eventing/sources/v1alpha1/apiserver_client_mock.go @@ -0,0 +1,108 @@ +// Copyright © 2019 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 implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v1alpha1 + +import ( + "testing" + + "knative.dev/eventing/pkg/apis/sources/v1alpha1" + + "knative.dev/client/pkg/util/mock" +) + +type MockKnApiServerSourceClient struct { + t *testing.T + recorder *ApiServerSourcesRecorder + namespace string +} + +// NewMockKnApiServerSourceClient returns a new mock instance which you need to record for +func NewMockKnApiServerSourceClient(t *testing.T, ns ...string) *MockKnApiServerSourceClient { + namespace := "default" + if len(ns) > 0 { + namespace = ns[0] + } + return &MockKnApiServerSourceClient{ + t: t, + recorder: &ApiServerSourcesRecorder{mock.NewRecorder(t, namespace)}, + } +} + +// Ensure that the interface is implemented +var _ KnApiServerSourcesClient = &MockKnApiServerSourceClient{} + +// recorder for service +type ApiServerSourcesRecorder struct { + r *mock.Recorder +} + +// Recorder returns the recorder for registering API calls +func (c *MockKnApiServerSourceClient) Recorder() *ApiServerSourcesRecorder { + return c.recorder +} + +// Namespace of this client +func (c *MockKnApiServerSourceClient) Namespace() string { + return c.recorder.r.Namespace() +} + +// GetApiServerSource records a call for GetApiServerSource with the expected object or error. Either apiServerSource or err should be nil +func (sr *ApiServerSourcesRecorder) GetApiServerSource(name interface{}, apiServerSource *v1alpha1.ApiServerSource, err error) { + sr.r.Add("GetApiServerSource", []interface{}{name}, []interface{}{apiServerSource, err}) +} + +// GetApiServerSource performs a previously recorded action, failing if non has been registered +func (c *MockKnApiServerSourceClient) GetApiServerSource(name string) (*v1alpha1.ApiServerSource, error) { + call := c.recorder.r.VerifyCall("GetApiServerSource", name) + return call.Result[0].(*v1alpha1.ApiServerSource), mock.ErrorOrNil(call.Result[1]) +} + +// CreateApiServerSource records a call for CreateApiServerSource with the expected error +func (sr *ApiServerSourcesRecorder) CreateApiServerSource(apiServerSource interface{}, err error) { + sr.r.Add("CreateApiServerSource", []interface{}{apiServerSource}, []interface{}{err}) +} + +// CreateApiServerSource performs a previously recorded action, failing if non has been registered +func (c *MockKnApiServerSourceClient) CreateApiServerSource(apiServerSource *v1alpha1.ApiServerSource) error { + call := c.recorder.r.VerifyCall("CreateApiServerSource", apiServerSource) + return mock.ErrorOrNil(call.Result[0]) +} + +// UpdateApiServerSource records a call for UpdateApiServerSource with the expected error (nil if none) +func (sr *ApiServerSourcesRecorder) UpdateApiServerSource(apiServerSource interface{}, err error) { + sr.r.Add("UpdateApiServerSource", []interface{}{apiServerSource}, []interface{}{err}) +} + +// UpdateApiServerSource performs a previously recorded action, failing if non has been registered +func (c *MockKnApiServerSourceClient) UpdateApiServerSource(apiServerSource *v1alpha1.ApiServerSource) error { + call := c.recorder.r.VerifyCall("UpdateApiServerSource", apiServerSource) + return mock.ErrorOrNil(call.Result[0]) +} + +// UpdateApiServerSource records a call for DeleteApiServerSource with the expected error (nil if none) +func (sr *ApiServerSourcesRecorder) DeleteApiServerSource(name interface{}, err error) { + sr.r.Add("DeleteApiServerSource", []interface{}{name}, []interface{}{err}) +} + +// DeleteApiServerSource performs a previously recorded action, failing if non has been registered +func (c *MockKnApiServerSourceClient) DeleteApiServerSource(name string) error { + call := c.recorder.r.VerifyCall("DeleteApiServerSource", name) + return mock.ErrorOrNil(call.Result[0]) +} + +// Validates validates whether every recorded action has been called +func (sr *ApiServerSourcesRecorder) Validate() { + sr.r.CheckThatAllRecordedMethodsHaveBeenCalled() +} diff --git a/pkg/eventing/sources/v1alpha1/apiserver_client_mock_test.go b/pkg/eventing/sources/v1alpha1/apiserver_client_mock_test.go new file mode 100644 index 0000000000..9a0b5cd0e1 --- /dev/null +++ b/pkg/eventing/sources/v1alpha1/apiserver_client_mock_test.go @@ -0,0 +1,43 @@ +// Copyright © 2019 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 implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v1alpha1 + +import ( + "testing" + + "knative.dev/eventing/pkg/apis/sources/v1alpha1" +) + +func TestMockKnApiServerSourceClient(t *testing.T) { + + client := NewMockKnApiServerSourceClient(t) + + recorder := client.Recorder() + + // Record all services + recorder.GetApiServerSource("hello", nil, nil) + recorder.CreateApiServerSource(&v1alpha1.ApiServerSource{}, nil) + recorder.UpdateApiServerSource(&v1alpha1.ApiServerSource{}, nil) + recorder.DeleteApiServerSource("hello", nil) + + // Call all service + client.GetApiServerSource("hello") + client.CreateApiServerSource(&v1alpha1.ApiServerSource{}) + client.UpdateApiServerSource(&v1alpha1.ApiServerSource{}) + client.DeleteApiServerSource("hello") + + // Validate + recorder.Validate() +} From 72fcd6a5f820d94af26b1ac13dda42a10c5ada9b Mon Sep 17 00:00:00 2001 From: Navid Shaikh Date: Sun, 15 Dec 2019 19:35:05 +0530 Subject: [PATCH 06/16] Add mock unit tests for create, delete and update --- pkg/kn/commands/source/apiserver/apiserver.go | 8 +- .../source/apiserver/apiserver_test.go | 114 ++++++++++++++++++ .../commands/source/apiserver/create_test.go | 64 ++++++++++ .../commands/source/apiserver/delete_test.go | 53 ++++++++ .../commands/source/apiserver/update_test.go | 54 +++++++++ 5 files changed, 289 insertions(+), 4 deletions(-) create mode 100644 pkg/kn/commands/source/apiserver/apiserver_test.go create mode 100644 pkg/kn/commands/source/apiserver/create_test.go create mode 100644 pkg/kn/commands/source/apiserver/delete_test.go create mode 100644 pkg/kn/commands/source/apiserver/update_test.go diff --git a/pkg/kn/commands/source/apiserver/apiserver.go b/pkg/kn/commands/source/apiserver/apiserver.go index 75b181113b..551014c487 100644 --- a/pkg/kn/commands/source/apiserver/apiserver.go +++ b/pkg/kn/commands/source/apiserver/apiserver.go @@ -20,7 +20,7 @@ import ( sources_v1alpha1 "knative.dev/eventing/pkg/client/clientset/versioned/typed/sources/v1alpha1" - "knative.dev/client/pkg/eventing/sources/v1alpha1" + knsources_v1alpha1 "knative.dev/client/pkg/eventing/sources/v1alpha1" "knative.dev/client/pkg/kn/commands" ) @@ -35,9 +35,9 @@ func NewApiServerCommand(p *commands.KnParams) *cobra.Command { return apiServerSourceCmd } -var apiServerSourceClientFactory func(config clientcmd.ClientConfig, namespace string) (v1alpha1.KnApiServerSourcesClient, error) +var apiServerSourceClientFactory func(config clientcmd.ClientConfig, namespace string) (knsources_v1alpha1.KnApiServerSourcesClient, error) -func newApiServerSourceClient(p *commands.KnParams, cmd *cobra.Command) (v1alpha1.KnApiServerSourcesClient, error) { +func newApiServerSourceClient(p *commands.KnParams, cmd *cobra.Command) (knsources_v1alpha1.KnApiServerSourcesClient, error) { namespace, err := p.GetNamespace(cmd) if err != nil { return nil, err @@ -61,5 +61,5 @@ func newApiServerSourceClient(p *commands.KnParams, cmd *cobra.Command) (v1alpha return nil, err } - return v1alpha1.NewKnSourcesClient(client, namespace).ApiServerSourcesClient(), nil + return knsources_v1alpha1.NewKnSourcesClient(client, namespace).ApiServerSourcesClient(), nil } diff --git a/pkg/kn/commands/source/apiserver/apiserver_test.go b/pkg/kn/commands/source/apiserver/apiserver_test.go new file mode 100644 index 0000000000..36533e1ea4 --- /dev/null +++ b/pkg/kn/commands/source/apiserver/apiserver_test.go @@ -0,0 +1,114 @@ +// Copyright © 2019 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 implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package apiserver + +import ( + "bytes" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/tools/clientcmd" + "knative.dev/eventing/pkg/apis/sources/v1alpha1" + duckv1beta1 "knative.dev/pkg/apis/duck/v1beta1" + + knsource_v1alpha1 "knative.dev/client/pkg/eventing/sources/v1alpha1" + "knative.dev/client/pkg/kn/commands" + knserving_v1alpha1 "knative.dev/client/pkg/serving/v1alpha1" +) + +const testNamespace = "default" + +// Helper methods +var blankConfig clientcmd.ClientConfig + +// TOOD: Remove that blankConfig hack for tests in favor of overwriting GetConfig() +func init() { + var err error + blankConfig, err = clientcmd.NewClientConfigFromBytes([]byte(`kind: Config +version: v1 +users: +- name: u +clusters: +- name: c + cluster: + server: example.com +contexts: +- name: x + context: + user: u + cluster: c +current-context: x +`)) + if err != nil { + panic(err) + } +} + +func executeApiServerSourceCommand(apiServerSourceClient knsource_v1alpha1.KnApiServerSourcesClient, servingClient knserving_v1alpha1.KnServingClient, args ...string) (string, error) { + knParams := &commands.KnParams{} + knParams.ClientConfig = blankConfig + + output := new(bytes.Buffer) + knParams.Output = output + knParams.NewServingClient = func(namespace string) (knserving_v1alpha1.KnServingClient, error) { + return servingClient, nil + } + + cmd := NewApiServerCommand(knParams) + cmd.SetArgs(args) + cmd.SetOutput(output) + + apiServerSourceClientFactory = func(config clientcmd.ClientConfig, namespace string) (knsource_v1alpha1.KnApiServerSourcesClient, error) { + return apiServerSourceClient, nil + } + defer cleanupApiServerMockClient() + + err := cmd.Execute() + + return output.String(), err +} + +func cleanupApiServerMockClient() { + apiServerSourceClientFactory = nil +} + +func createApiServerSource(name, resourceKind, resourceVersion, serviceAccount, mode, service string, isController bool) *v1alpha1.ApiServerSource { + source := &v1alpha1.ApiServerSource{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: testNamespace, + }, + Spec: v1alpha1.ApiServerSourceSpec{ + Resources: []v1alpha1.ApiServerResource{ + { + APIVersion: resourceVersion, + Kind: resourceKind, + Controller: isController, + }, + }, + ServiceAccountName: serviceAccount, + Mode: mode, + }, + } + + source.Spec.Sink = &duckv1beta1.Destination{ + Ref: &corev1.ObjectReference{ + Kind: "Service", + Name: service, + }, + } + + return source +} diff --git a/pkg/kn/commands/source/apiserver/create_test.go b/pkg/kn/commands/source/apiserver/create_test.go new file mode 100644 index 0000000000..0ed9075d84 --- /dev/null +++ b/pkg/kn/commands/source/apiserver/create_test.go @@ -0,0 +1,64 @@ +// Copyright © 2019 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 implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package apiserver + +import ( + "errors" + "testing" + + "gotest.tools/assert" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + serving_v1alpha1 "knative.dev/serving/pkg/apis/serving/v1alpha1" + + knsources_v1alpha1 "knative.dev/client/pkg/eventing/sources/v1alpha1" + knserving_client "knative.dev/client/pkg/serving/v1alpha1" + "knative.dev/client/pkg/util" +) + +func TestCreateApiServerSource(t *testing.T) { + + apiServerClient := knsources_v1alpha1.NewMockKnApiServerSourceClient(t) + servingClient := knserving_client.NewMockKnServiceClient(t) + + servingRecorder := servingClient.Recorder() + servingRecorder.GetService("testsvc", &serving_v1alpha1.Service{ + TypeMeta: metav1.TypeMeta{Kind: "Service"}, + ObjectMeta: metav1.ObjectMeta{Name: "testsvc"}, + }, nil) + + apiServerRecorder := apiServerClient.Recorder() + apiServerRecorder.CreateApiServerSource(createApiServerSource("testsource", "Event", "v1", "testsa", "Ref", "testsvc", false), nil) + + out, err := executeApiServerSourceCommand(apiServerClient, servingClient, "create", "testsource", "--resource", "Event:v1:false", "--service-account", "testsa", "--sink", "svc:testsvc", "--mode", "Ref") + assert.NilError(t, err, "ApiServer source should be created") + util.ContainsAll(out, "created", "default", "testsource") + + apiServerRecorder.Validate() + servingRecorder.Validate() +} + +func TestNoSinkError(t *testing.T) { + servingClient := knserving_client.NewMockKnServiceClient(t) + apiServerClient := knsources_v1alpha1.NewMockKnApiServerSourceClient(t) + + errorMsg := "cannot create ApiServerSource 'testsource' in namespace 'default' because no Service svc found" + servingRecorder := servingClient.Recorder() + servingRecorder.GetService("testsvc", nil, errors.New("no Service svc found")) + + out, err := executeApiServerSourceCommand(apiServerClient, servingClient, "create", "testsource", "--resource", "Event:v1:false", "--service-account", "testsa", "--sink", "svc:testsvc", "--mode", "Ref") + assert.Error(t, err, errorMsg) + assert.Assert(t, util.ContainsAll(out, errorMsg, "Usage")) + servingRecorder.Validate() +} diff --git a/pkg/kn/commands/source/apiserver/delete_test.go b/pkg/kn/commands/source/apiserver/delete_test.go new file mode 100644 index 0000000000..3dcea96cf5 --- /dev/null +++ b/pkg/kn/commands/source/apiserver/delete_test.go @@ -0,0 +1,53 @@ +// Copyright © 2019 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 implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package apiserver + +import ( + "errors" + "testing" + + "gotest.tools/assert" + + knsources_v1alpha1 "knative.dev/client/pkg/eventing/sources/v1alpha1" + "knative.dev/client/pkg/util" +) + +func TestApiServerSourceDelete(t *testing.T) { + + apiServerClient := knsources_v1alpha1.NewMockKnApiServerSourceClient(t, "testns") + apiServerRecorder := apiServerClient.Recorder() + + apiServerRecorder.DeleteApiServerSource("testsource", nil) + + out, err := executeApiServerSourceCommand(apiServerClient, nil, "delete", "testsource") + assert.NilError(t, err) + util.ContainsAll(out, "deleted", "testns", "testsource") + + apiServerRecorder.Validate() +} + +func TestDeleteWithError(t *testing.T) { + + apiServerClient := knsources_v1alpha1.NewMockKnApiServerSourceClient(t, "mynamespace") + apiServerRecorder := apiServerClient.Recorder() + + apiServerRecorder.DeleteApiServerSource("testsource", errors.New("apiserver source testsource not found")) + + out, err := executeApiServerSourceCommand(apiServerClient, nil, "delete", "testsource") + assert.ErrorContains(t, err, "testsource") + util.ContainsAll(out, "apiserver", "source", "testsource", "not found") + + apiServerRecorder.Validate() +} diff --git a/pkg/kn/commands/source/apiserver/update_test.go b/pkg/kn/commands/source/apiserver/update_test.go new file mode 100644 index 0000000000..4eaf62033d --- /dev/null +++ b/pkg/kn/commands/source/apiserver/update_test.go @@ -0,0 +1,54 @@ +// Copyright © 2019 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 implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package apiserver + +import ( + "testing" + + "gotest.tools/assert" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + serving_v1alpha1 "knative.dev/serving/pkg/apis/serving/v1alpha1" + + knsources_v1alpha1 "knative.dev/client/pkg/eventing/sources/v1alpha1" + knserving_client "knative.dev/client/pkg/serving/v1alpha1" + "knative.dev/client/pkg/util" +) + +func TestApiServerSourceUpdate(t *testing.T) { + apiServerClient := knsources_v1alpha1.NewMockKnApiServerSourceClient(t) + servingClient := knserving_client.NewMockKnServiceClient(t) + + apiServerRecorder := apiServerClient.Recorder() + servingRecorder := servingClient.Recorder() + + present := createApiServerSource("testsource", "Event", "v1", "testsa1", "Ref", "svc1", false) + apiServerRecorder.GetApiServerSource("testsource", present, nil) + + servingRecorder.GetService("svc2", &serving_v1alpha1.Service{ + TypeMeta: metav1.TypeMeta{Kind: "Service"}, + ObjectMeta: metav1.ObjectMeta{Name: "svc2"}, + }, nil) + + updated := createApiServerSource("testsource", "Event", "v1", "testsa2", "Ref", "svc2", false) + apiServerRecorder.UpdateApiServerSource(updated, nil) + + output, err := executeApiServerSourceCommand(apiServerClient, servingClient, "update", "testsource", "--service-account", "testsa2", "--sink", "svc:svc2") + assert.NilError(t, err) + assert.Assert(t, util.ContainsAll(output, "testsource", "updated", "default")) + + apiServerRecorder.Validate() + servingRecorder.Validate() +} From 43408fc82632045b16cf11bbb538a4e24e8e0d0b Mon Sep 17 00:00:00 2001 From: Navid Shaikh Date: Sun, 15 Dec 2019 22:12:44 +0530 Subject: [PATCH 07/16] Add e2e tests for apiserver source update - Add a test for apiserver source sink update - Verify the updated sink name after the apiserver source is created - Update resource names in existing tests --- test/e2e/source_apiserver_test.go | 61 ++++++++++++++++++++++--------- 1 file changed, 44 insertions(+), 17 deletions(-) diff --git a/test/e2e/source_apiserver_test.go b/test/e2e/source_apiserver_test.go index 7666777d25..48a98e82b6 100644 --- a/test/e2e/source_apiserver_test.go +++ b/test/e2e/source_apiserver_test.go @@ -31,41 +31,52 @@ func TestSourceApiServer(t *testing.T) { test.Setup(t) defer test.Teardown(t) - test.setupServiceAccountForApiserver(t, "mysa") - test.serviceCreate(t, "myservice") + test.setupServiceAccountForApiserver(t, "testsa") + test.serviceCreate(t, "testsvc0") - t.Run("create apiserver source with a sink to a service", func(t *testing.T) { - test.apiServerSourceCreate(t, "firstsrc", "Eventing:v1:true", "mysa", "svc:myservice") - test.apiServerSourceCreate(t, "secondsrc", "Eventing,Namespace", "mysa", "svc:myservice") + t.Run("create apiserver sources with a sink to a service", func(t *testing.T) { + test.apiServerSourceCreate(t, "testapisource0", "Event:v1:true", "testsa", "svc:testsvc0") + test.apiServerSourceCreate(t, "testapisource1", "Event", "testsa", "svc:testsvc0") }) - t.Run("create apiserver source and delete it", func(t *testing.T) { - test.apiServerSourceDelete(t, "firstsrc") - test.apiServerSourceDelete(t, "secondsrc") + t.Run("delete apiserver sources", func(t *testing.T) { + test.apiServerSourceDelete(t, "testapisource0") + test.apiServerSourceDelete(t, "testapisource1") }) t.Run("create apiserver source with a missing sink service", func(t *testing.T) { - test.apiServerSourceCreateMissingSink(t, "wrongsrc", "Eventing:v1:true", "mysa", "svc:unknown") + test.apiServerSourceCreateMissingSink(t, "testapisource2", "Event:v1:true", "testsa", "svc:unknown") + }) + + t.Run("update apiserver source sink service", func(t *testing.T) { + test.apiServerSourceCreate(t, "testapisource3", "Event:1:true", "testsa", "svc:testsvc0") + test.serviceCreate(t, "testsvc1") + test.apiServerSourceUpdateSink(t, "testapisource3", "svc:testsvc1") + jpSinkRefNameInSpec := "jsonpath={.spec.sink.ref.name}" + out, err := test.k8sGetResourceJsonPath(t, "apiserversource", "testapisource3", jpSinkRefNameInSpec) + assert.NilError(t, err) + assert.Equal(t, out, "testsvc1") + // TODO(navidshaikh): Verify the source's status with synchronous create/update }) } -func (test *e2eTest) apiServerSourceCreate(t *testing.T, srcName string, resources string, sa string, sink string) { - out, err := test.kn.RunWithOpts([]string{"source", "apiserver", "create", srcName, +func (test *e2eTest) apiServerSourceCreate(t *testing.T, sourceName string, resources string, sa string, sink string) { + out, err := test.kn.RunWithOpts([]string{"source", "apiserver", "create", sourceName, "--resource", resources, "--service-account", sa, "--sink", sink}, runOpts{NoNamespace: false}) assert.NilError(t, err) - assert.Check(t, util.ContainsAllIgnoreCase(out, "ApiServerSource", srcName, "created", "namespace", test.kn.namespace)) + assert.Check(t, util.ContainsAllIgnoreCase(out, "ApiServerSource", sourceName, "created", "namespace", test.kn.namespace)) } -func (test *e2eTest) apiServerSourceCreateMissingSink(t *testing.T, srcName string, resources string, sa string, sink string) { - _, err := test.kn.RunWithOpts([]string{"source", "apiserver", "create", srcName, +func (test *e2eTest) apiServerSourceCreateMissingSink(t *testing.T, sourceName string, resources string, sa string, sink string) { + _, err := test.kn.RunWithOpts([]string{"source", "apiserver", "create", sourceName, "--resource", resources, "--service-account", sa, "--sink", sink}, runOpts{NoNamespace: false, AllowError: true}) assert.ErrorContains(t, err, "services.serving.knative.dev", "not found") } -func (test *e2eTest) apiServerSourceDelete(t *testing.T, srcName string) { - out, err := test.kn.RunWithOpts([]string{"source", "apiserver", "delete", srcName}, runOpts{NoNamespace: false}) +func (test *e2eTest) apiServerSourceDelete(t *testing.T, sourceName string) { + out, err := test.kn.RunWithOpts([]string{"source", "apiserver", "delete", sourceName}, runOpts{NoNamespace: false}) assert.NilError(t, err) - assert.Check(t, util.ContainsAllIgnoreCase(out, "ApiServerSource", srcName, "deleted", "namespace", test.kn.namespace)) + assert.Check(t, util.ContainsAllIgnoreCase(out, "ApiServerSource", sourceName, "deleted", "namespace", test.kn.namespace)) } func (test *e2eTest) setupServiceAccountForApiserver(t *testing.T, name string) { @@ -84,3 +95,19 @@ func (test *e2eTest) setupServiceAccountForApiserver(t *testing.T, name string) t.Fatalf(fmt.Sprintf("Error executing 'kubectl clusterrolebinding testsa-binding'. Error: %s", err.Error())) } } + +func (test *e2eTest) apiServerSourceUpdateSink(t *testing.T, sourceName string, sink string) { + out, err := test.kn.RunWithOpts([]string{"source", "apiserver", "update", sourceName, "--sink", sink}, runOpts{}) + assert.NilError(t, err) + assert.Check(t, util.ContainsAll(out, sourceName, "updated", "namespace", test.kn.namespace)) +} + +func (test *e2eTest) k8sGetResourceJsonPath(t *testing.T, resource, name, jsonpath string) (string, error) { + kubectl := kubectl{t, Logger{}} + out, err := kubectl.RunWithOpts([]string{"get", resource, name, "-o", jsonpath, "-n", test.kn.namespace}, runOpts{}) + if err != nil { + return "", err + } + + return out, nil +} From 72063c4c919450c75229c96185a13a0e1abba3a0 Mon Sep 17 00:00:00 2001 From: Navid Shaikh Date: Mon, 16 Dec 2019 00:48:48 +0530 Subject: [PATCH 08/16] Uses builder pattern for ApiServer source create command --- docs/cmd/kn_source_apiserver.md | 2 +- docs/cmd/kn_source_apiserver_update.md | 4 +- .../sources/v1alpha1/apiserver_client.go | 45 +++++++++++++++- .../source/apiserver/apiserver_test.go | 37 +++++-------- pkg/kn/commands/source/apiserver/create.go | 54 +++++++------------ .../commands/source/apiserver/create_test.go | 3 +- pkg/kn/commands/source/apiserver/update.go | 2 +- 7 files changed, 81 insertions(+), 66 deletions(-) diff --git a/docs/cmd/kn_source_apiserver.md b/docs/cmd/kn_source_apiserver.md index 5cfb43b7a8..5258006825 100644 --- a/docs/cmd/kn_source_apiserver.md +++ b/docs/cmd/kn_source_apiserver.md @@ -29,5 +29,5 @@ kn source apiserver [flags] * [kn source](kn_source.md) - Event source command group * [kn source apiserver create](kn_source_apiserver_create.md) - Create an ApiServerSource, which watches for Kubernetes events and forwards them to a sink * [kn source apiserver delete](kn_source_apiserver_delete.md) - Delete an ApiServerSource. -* [kn source apiserver update](kn_source_apiserver_update.md) - update an ApiServerSource, which watches for Kubernetes events and forwards them to a sink +* [kn source apiserver update](kn_source_apiserver_update.md) - Update an ApiServerSource, which watches for Kubernetes events and forwards them to a sink diff --git a/docs/cmd/kn_source_apiserver_update.md b/docs/cmd/kn_source_apiserver_update.md index 0779ec4b7e..b0928c41de 100644 --- a/docs/cmd/kn_source_apiserver_update.md +++ b/docs/cmd/kn_source_apiserver_update.md @@ -1,10 +1,10 @@ ## kn source apiserver update -update an ApiServerSource, which watches for Kubernetes events and forwards them to a sink +Update an ApiServerSource, which watches for Kubernetes events and forwards them to a sink ### Synopsis -update an ApiServerSource, which watches for Kubernetes events and forwards them to a sink +Update an ApiServerSource, which watches for Kubernetes events and forwards them to a sink ``` kn source apiserver update NAME --resource RESOURCE --service-account ACCOUNTNAME --sink SINK --mode MODE [flags] diff --git a/pkg/eventing/sources/v1alpha1/apiserver_client.go b/pkg/eventing/sources/v1alpha1/apiserver_client.go index aba7d43e27..1f6154b9bd 100644 --- a/pkg/eventing/sources/v1alpha1/apiserver_client.go +++ b/pkg/eventing/sources/v1alpha1/apiserver_client.go @@ -16,10 +16,10 @@ package v1alpha1 import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + kn_errors "knative.dev/client/pkg/errors" "knative.dev/eventing/pkg/apis/sources/v1alpha1" client_v1alpha1 "knative.dev/eventing/pkg/client/clientset/versioned/typed/sources/v1alpha1" - - kn_errors "knative.dev/client/pkg/errors" + duckv1beta1 "knative.dev/pkg/apis/duck/v1beta1" ) // Interface for working with ApiServer sources @@ -97,3 +97,44 @@ func (c *apiServerSourcesClient) DeleteApiServerSource(name string) error { func (c *apiServerSourcesClient) Namespace() string { return c.namespace } + +// APIServerSourceBuilder is for building the source +type APIServerSourceBuilder struct { + apiServerSource *v1alpha1.ApiServerSource +} + +func NewAPIServerSourceBuilder(name string) *APIServerSourceBuilder { + return &APIServerSourceBuilder{apiServerSource: &v1alpha1.ApiServerSource{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + }, + }} +} + +func NewAPIServerSourceBuilderFromExisting(apiServerSource *v1alpha1.ApiServerSource) *APIServerSourceBuilder { + return &APIServerSourceBuilder{apiServerSource: apiServerSource.DeepCopy()} +} + +func (b *APIServerSourceBuilder) Resources(resources []v1alpha1.ApiServerResource) *APIServerSourceBuilder { + b.apiServerSource.Spec.Resources = resources + return b +} + +func (b *APIServerSourceBuilder) ServiceAccount(sa string) *APIServerSourceBuilder { + b.apiServerSource.Spec.ServiceAccountName = sa + return b +} + +func (b *APIServerSourceBuilder) Mode(mode string) *APIServerSourceBuilder { + b.apiServerSource.Spec.Mode = mode + return b +} + +func (b *APIServerSourceBuilder) Sink(sink *duckv1beta1.Destination) *APIServerSourceBuilder { + b.apiServerSource.Spec.Sink = sink + return b +} + +func (b *APIServerSourceBuilder) Build() *v1alpha1.ApiServerSource { + return b.apiServerSource +} diff --git a/pkg/kn/commands/source/apiserver/apiserver_test.go b/pkg/kn/commands/source/apiserver/apiserver_test.go index 36533e1ea4..e260fcb162 100644 --- a/pkg/kn/commands/source/apiserver/apiserver_test.go +++ b/pkg/kn/commands/source/apiserver/apiserver_test.go @@ -18,7 +18,6 @@ import ( "bytes" corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/tools/clientcmd" "knative.dev/eventing/pkg/apis/sources/v1alpha1" duckv1beta1 "knative.dev/pkg/apis/duck/v1beta1" @@ -85,30 +84,22 @@ func cleanupApiServerMockClient() { } func createApiServerSource(name, resourceKind, resourceVersion, serviceAccount, mode, service string, isController bool) *v1alpha1.ApiServerSource { - source := &v1alpha1.ApiServerSource{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: testNamespace, - }, - Spec: v1alpha1.ApiServerSourceSpec{ - Resources: []v1alpha1.ApiServerResource{ - { - APIVersion: resourceVersion, - Kind: resourceKind, - Controller: isController, - }, - }, - ServiceAccountName: serviceAccount, - Mode: mode, - }, - } + resources := []v1alpha1.ApiServerResource{{ + APIVersion: resourceVersion, + Kind: resourceKind, + Controller: isController, + }} - source.Spec.Sink = &duckv1beta1.Destination{ + sink := &duckv1beta1.Destination{ Ref: &corev1.ObjectReference{ Kind: "Service", Name: service, - }, - } - - return source + }} + + return knsource_v1alpha1.NewAPIServerSourceBuilder(name). + Resources(resources). + ServiceAccount(serviceAccount). + Mode(mode). + Sink(sink). + Build() } diff --git a/pkg/kn/commands/source/apiserver/create.go b/pkg/kn/commands/source/apiserver/create.go index 35a3ccd5a2..e2a4c191b5 100644 --- a/pkg/kn/commands/source/apiserver/create.go +++ b/pkg/kn/commands/source/apiserver/create.go @@ -20,10 +20,9 @@ import ( "github.com/spf13/cobra" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "knative.dev/client/pkg/eventing/sources/v1alpha1" "knative.dev/client/pkg/kn/commands" "knative.dev/client/pkg/kn/commands/flags" - "knative.dev/eventing/pkg/apis/sources/v1alpha1" ) func NewApiServerCreateCommand(p *commands.KnParams) *cobra.Command { @@ -39,23 +38,19 @@ func NewApiServerCreateCommand(p *commands.KnParams) *cobra.Command { RunE: func(cmd *cobra.Command, args []string) (err error) { if len(args) != 1 { - return errors.New("'source apiserver create' requires the name of the source as single argument") + return errors.New("requires the name of the APIServer source to create as single argument") } name := args[0] - // get namespace - namespace, err := p.GetNamespace(cmd) - if err != nil { - return err - } - // get client apiSourceClient, err := newApiServerSourceClient(p, cmd) if err != nil { return err } - // resolve sink + namespace := apiSourceClient.Namespace() + + // create Serving client for resolving service sink servingClient, err := p.NewServingClient(namespace) if err != nil { return err @@ -68,19 +63,26 @@ func NewApiServerCreateCommand(p *commands.KnParams) *cobra.Command { "because %s", name, namespace, err) } - // construct ApiServerSource - apisrvsrc := constructApiServerSource(name, namespace, apiServerUpdateFlags) - apisrvsrc.Spec.Sink = objectRef - // create - err = apiSourceClient.CreateApiServerSource(apisrvsrc) + err = apiSourceClient.CreateApiServerSource( + v1alpha1.NewAPIServerSourceBuilder(name). + Resources(apiServerUpdateFlags.GetApiServerResourceArray()). + ServiceAccount(apiServerUpdateFlags.ServiceAccountName). + Mode(apiServerUpdateFlags.Mode). + Sink(objectRef). + Build()) + if err != nil { return fmt.Errorf( "cannot create ApiServerSource '%s' in namespace '%s' "+ "because %s", name, namespace, err) } - fmt.Fprintf(cmd.OutOrStdout(), "ApiServerSource '%s' successfully created in namespace '%s'.\n", args[0], namespace) - return nil + + if err == nil { + fmt.Fprintf(cmd.OutOrStdout(), "ApiServer source '%s' created in namespace '%s'.\n", args[0], namespace) + } + + return err }, } commands.AddNamespaceFlags(cmd.Flags(), false) @@ -90,21 +92,3 @@ func NewApiServerCreateCommand(p *commands.KnParams) *cobra.Command { return cmd } - -// constructApiServerSource is to create an instance of v1alpha1.ApiServerSource -func constructApiServerSource(name string, namespace string, apiServerFlags ApiServerSourceUpdateFlags) *v1alpha1.ApiServerSource { - - source := v1alpha1.ApiServerSource{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: namespace, - }, - Spec: v1alpha1.ApiServerSourceSpec{ - Resources: apiServerFlags.GetApiServerResourceArray(), - ServiceAccountName: apiServerFlags.ServiceAccountName, - Mode: apiServerFlags.Mode, - }, - } - - return &source -} diff --git a/pkg/kn/commands/source/apiserver/create_test.go b/pkg/kn/commands/source/apiserver/create_test.go index 0ed9075d84..17a6cc05b4 100644 --- a/pkg/kn/commands/source/apiserver/create_test.go +++ b/pkg/kn/commands/source/apiserver/create_test.go @@ -20,11 +20,10 @@ import ( "gotest.tools/assert" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - serving_v1alpha1 "knative.dev/serving/pkg/apis/serving/v1alpha1" - knsources_v1alpha1 "knative.dev/client/pkg/eventing/sources/v1alpha1" knserving_client "knative.dev/client/pkg/serving/v1alpha1" "knative.dev/client/pkg/util" + serving_v1alpha1 "knative.dev/serving/pkg/apis/serving/v1alpha1" ) func TestCreateApiServerSource(t *testing.T) { diff --git a/pkg/kn/commands/source/apiserver/update.go b/pkg/kn/commands/source/apiserver/update.go index a5411eb82c..c9a010dde4 100644 --- a/pkg/kn/commands/source/apiserver/update.go +++ b/pkg/kn/commands/source/apiserver/update.go @@ -30,7 +30,7 @@ func NewApiServerUpdateCommand(p *commands.KnParams) *cobra.Command { cmd := &cobra.Command{ Use: "update NAME --resource RESOURCE --service-account ACCOUNTNAME --sink SINK --mode MODE", - Short: "update an ApiServerSource, which watches for Kubernetes events and forwards them to a sink", + Short: "Update an ApiServerSource, which watches for Kubernetes events and forwards them to a sink", Example: ` # Update an ApiServerSource 'k8sevents' with different service account and sink service kn source apiserver update k8sevents --service-account newsa --sink svc:newsvc`, From 23adcddaecc8415eac99a51cbbb4aa94665e74c5 Mon Sep 17 00:00:00 2001 From: Navid Shaikh Date: Mon, 16 Dec 2019 15:16:27 +0530 Subject: [PATCH 09/16] Update ApiServer source create/update flags and required config --- pkg/kn/commands/source/apiserver/create.go | 2 +- pkg/kn/commands/source/apiserver/flags.go | 2 +- pkg/kn/commands/source/apiserver/update.go | 23 ++++++++++------------ 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/pkg/kn/commands/source/apiserver/create.go b/pkg/kn/commands/source/apiserver/create.go index e2a4c191b5..3d29ca52ba 100644 --- a/pkg/kn/commands/source/apiserver/create.go +++ b/pkg/kn/commands/source/apiserver/create.go @@ -88,7 +88,7 @@ func NewApiServerCreateCommand(p *commands.KnParams) *cobra.Command { commands.AddNamespaceFlags(cmd.Flags(), false) apiServerUpdateFlags.Add(cmd) sinkFlags.Add(cmd) - cmd.MarkFlagRequired("schedule") + cmd.MarkFlagRequired("resource") return cmd } diff --git a/pkg/kn/commands/source/apiserver/flags.go b/pkg/kn/commands/source/apiserver/flags.go index 9224ea38e8..02eee6c1fd 100644 --- a/pkg/kn/commands/source/apiserver/flags.go +++ b/pkg/kn/commands/source/apiserver/flags.go @@ -94,7 +94,7 @@ func (f *ApiServerSourceUpdateFlags) Apply(source *v1alpha1.ApiServerSource, cmd source.Spec.ServiceAccountName = f.ServiceAccountName } - if cmd.Flags().Changed("mod") { + if cmd.Flags().Changed("mode") { source.Spec.Mode = f.Mode } diff --git a/pkg/kn/commands/source/apiserver/update.go b/pkg/kn/commands/source/apiserver/update.go index c9a010dde4..11f3ff532f 100644 --- a/pkg/kn/commands/source/apiserver/update.go +++ b/pkg/kn/commands/source/apiserver/update.go @@ -47,7 +47,6 @@ func NewApiServerUpdateCommand(p *commands.KnParams) *cobra.Command { return err } - // get client sourcesClient, err := newApiServerSourceClient(p, cmd) if err != nil { return err @@ -58,30 +57,28 @@ func NewApiServerUpdateCommand(p *commands.KnParams) *cobra.Command { return err } - // resolve sink servingClient, err := p.NewServingClient(namespace) if err != nil { return err } - objectRef, err := sinkFlags.ResolveSink(servingClient) - if err != nil { - return fmt.Errorf( - "cannot update ApiServerSource '%s' in namespace '%s' "+ - "because %v", name, namespace, err) + if cmd.Flags().Changed("sink") { + objectRef, err := sinkFlags.ResolveSink(servingClient) + if err != nil { + return err + } + + source.Spec.Sink = objectRef } - source = source.DeepCopy() apiServerUpdateFlags.Apply(source, cmd) - source.Spec.Sink = objectRef err = sourcesClient.UpdateApiServerSource(source) if err != nil { - return fmt.Errorf( - "cannot create ApiServerSource '%s' in namespace '%s' "+ - "because %s", name, namespace, err) + return err } - fmt.Fprintf(cmd.OutOrStdout(), "ApiServerSource '%s' updated in namespace '%s'.\n", args[0], namespace) + + fmt.Fprintf(cmd.OutOrStdout(), "ApiServer source '%s' updated in namespace '%s'.\n", args[0], namespace) return nil }, } From f7af01a060aa6300dbc259fb8ee73cdf7b219b39 Mon Sep 17 00:00:00 2001 From: Navid Shaikh Date: Mon, 16 Dec 2019 15:31:59 +0530 Subject: [PATCH 10/16] Uses builder pattern for ApiServer source update command --- pkg/kn/commands/source/apiserver/flags.go | 15 ---------- pkg/kn/commands/source/apiserver/update.go | 34 ++++++++++++++-------- 2 files changed, 22 insertions(+), 27 deletions(-) diff --git a/pkg/kn/commands/source/apiserver/flags.go b/pkg/kn/commands/source/apiserver/flags.go index 02eee6c1fd..d4d92deb30 100644 --- a/pkg/kn/commands/source/apiserver/flags.go +++ b/pkg/kn/commands/source/apiserver/flags.go @@ -87,18 +87,3 @@ func (f *ApiServerSourceUpdateFlags) Add(cmd *cobra.Command) { "APIVersion" and "isControler" can be omitted. "APIVersion" is "v1" by default, "isController" is "false" by default.`) } - -//Apply updates the service object based on flags -func (f *ApiServerSourceUpdateFlags) Apply(source *v1alpha1.ApiServerSource, cmd *cobra.Command) { - if cmd.Flags().Changed("service-account") { - source.Spec.ServiceAccountName = f.ServiceAccountName - } - - if cmd.Flags().Changed("mode") { - source.Spec.Mode = f.Mode - } - - if cmd.Flags().Changed("resource") { - source.Spec.Resources = f.GetApiServerResourceArray() - } -} diff --git a/pkg/kn/commands/source/apiserver/update.go b/pkg/kn/commands/source/apiserver/update.go index 11f3ff532f..8e7c42647d 100644 --- a/pkg/kn/commands/source/apiserver/update.go +++ b/pkg/kn/commands/source/apiserver/update.go @@ -20,6 +20,7 @@ import ( "github.com/spf13/cobra" + "knative.dev/client/pkg/eventing/sources/v1alpha1" "knative.dev/client/pkg/kn/commands" "knative.dev/client/pkg/kn/commands/flags" ) @@ -47,39 +48,48 @@ func NewApiServerUpdateCommand(p *commands.KnParams) *cobra.Command { return err } - sourcesClient, err := newApiServerSourceClient(p, cmd) + servingClient, err := p.NewServingClient(namespace) if err != nil { return err } - source, err := sourcesClient.GetApiServerSource(name) + sourcesClient, err := newApiServerSourceClient(p, cmd) if err != nil { return err } - servingClient, err := p.NewServingClient(namespace) + source, err := sourcesClient.GetApiServerSource(name) if err != nil { return err } + b := v1alpha1.NewAPIServerSourceBuilderFromExisting(source) + if cmd.Flags().Changed("service-account") { + b.ServiceAccount(apiServerUpdateFlags.ServiceAccountName) + } + + if cmd.Flags().Changed("mode") { + b.Mode(apiServerUpdateFlags.Mode) + } + + if cmd.Flags().Changed("resource") { + b.Resources(apiServerUpdateFlags.GetApiServerResourceArray()) + } + if cmd.Flags().Changed("sink") { objectRef, err := sinkFlags.ResolveSink(servingClient) if err != nil { return err } - - source.Spec.Sink = objectRef + b.Sink(objectRef) } - apiServerUpdateFlags.Apply(source, cmd) - - err = sourcesClient.UpdateApiServerSource(source) - if err != nil { - return err + err = sourcesClient.UpdateApiServerSource(b.Build()) + if err == nil { + fmt.Fprintf(cmd.OutOrStdout(), "ApiServer source '%s' updated in namespace '%s'.\n", args[0], namespace) } - fmt.Fprintf(cmd.OutOrStdout(), "ApiServer source '%s' updated in namespace '%s'.\n", args[0], namespace) - return nil + return err }, } commands.AddNamespaceFlags(cmd.Flags(), false) From 6418749cdc6161392ca88bb2cdde6d6e27225659 Mon Sep 17 00:00:00 2001 From: Navid Shaikh Date: Mon, 16 Dec 2019 15:37:36 +0530 Subject: [PATCH 11/16] Align create/update/delete description and error messages --- docs/cmd/kn_source_apiserver.md | 6 +++--- docs/cmd/kn_source_apiserver_create.md | 4 ++-- docs/cmd/kn_source_apiserver_delete.md | 4 ++-- docs/cmd/kn_source_apiserver_update.md | 4 ++-- pkg/kn/commands/source/apiserver/create.go | 4 ++-- pkg/kn/commands/source/apiserver/delete.go | 4 ++-- pkg/kn/commands/source/apiserver/update.go | 2 +- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/cmd/kn_source_apiserver.md b/docs/cmd/kn_source_apiserver.md index 5258006825..7348023f18 100644 --- a/docs/cmd/kn_source_apiserver.md +++ b/docs/cmd/kn_source_apiserver.md @@ -27,7 +27,7 @@ kn source apiserver [flags] ### SEE ALSO * [kn source](kn_source.md) - Event source command group -* [kn source apiserver create](kn_source_apiserver_create.md) - Create an ApiServerSource, which watches for Kubernetes events and forwards them to a sink -* [kn source apiserver delete](kn_source_apiserver_delete.md) - Delete an ApiServerSource. -* [kn source apiserver update](kn_source_apiserver_update.md) - Update an ApiServerSource, which watches for Kubernetes events and forwards them to a sink +* [kn source apiserver create](kn_source_apiserver_create.md) - Create an ApiServer source. +* [kn source apiserver delete](kn_source_apiserver_delete.md) - Delete an ApiServer source. +* [kn source apiserver update](kn_source_apiserver_update.md) - Update an ApiServerSource. diff --git a/docs/cmd/kn_source_apiserver_create.md b/docs/cmd/kn_source_apiserver_create.md index e8a1cb7fcf..ec3efddf16 100644 --- a/docs/cmd/kn_source_apiserver_create.md +++ b/docs/cmd/kn_source_apiserver_create.md @@ -1,10 +1,10 @@ ## kn source apiserver create -Create an ApiServerSource, which watches for Kubernetes events and forwards them to a sink +Create an ApiServer source. ### Synopsis -Create an ApiServerSource, which watches for Kubernetes events and forwards them to a sink +Create an ApiServer source. ``` kn source apiserver create NAME --resource RESOURCE --service-account ACCOUNTNAME --sink SINK --mode MODE [flags] diff --git a/docs/cmd/kn_source_apiserver_delete.md b/docs/cmd/kn_source_apiserver_delete.md index 9b362ca860..3faff99faa 100644 --- a/docs/cmd/kn_source_apiserver_delete.md +++ b/docs/cmd/kn_source_apiserver_delete.md @@ -1,10 +1,10 @@ ## kn source apiserver delete -Delete an ApiServerSource. +Delete an ApiServer source. ### Synopsis -Delete an ApiServerSource. +Delete an ApiServer source. ``` kn source apiserver delete NAME [flags] diff --git a/docs/cmd/kn_source_apiserver_update.md b/docs/cmd/kn_source_apiserver_update.md index b0928c41de..b918d4d947 100644 --- a/docs/cmd/kn_source_apiserver_update.md +++ b/docs/cmd/kn_source_apiserver_update.md @@ -1,10 +1,10 @@ ## kn source apiserver update -Update an ApiServerSource, which watches for Kubernetes events and forwards them to a sink +Update an ApiServerSource. ### Synopsis -Update an ApiServerSource, which watches for Kubernetes events and forwards them to a sink +Update an ApiServerSource. ``` kn source apiserver update NAME --resource RESOURCE --service-account ACCOUNTNAME --sink SINK --mode MODE [flags] diff --git a/pkg/kn/commands/source/apiserver/create.go b/pkg/kn/commands/source/apiserver/create.go index 3d29ca52ba..4c6300a05c 100644 --- a/pkg/kn/commands/source/apiserver/create.go +++ b/pkg/kn/commands/source/apiserver/create.go @@ -31,14 +31,14 @@ func NewApiServerCreateCommand(p *commands.KnParams) *cobra.Command { cmd := &cobra.Command{ Use: "create NAME --resource RESOURCE --service-account ACCOUNTNAME --sink SINK --mode MODE", - Short: "Create an ApiServerSource, which watches for Kubernetes events and forwards them to a sink", + Short: "Create an ApiServer source.", Example: ` # Create an ApiServerSource 'k8sevents' which consumes Kubernetes events and sends message to service 'mysvc' as a cloudevent kn source apiserver create k8sevents --resource Event --service-account myaccountname --sink svc:mysvc`, RunE: func(cmd *cobra.Command, args []string) (err error) { if len(args) != 1 { - return errors.New("requires the name of the APIServer source to create as single argument") + return errors.New("requires the name of the source to create as single argument") } name := args[0] diff --git a/pkg/kn/commands/source/apiserver/delete.go b/pkg/kn/commands/source/apiserver/delete.go index 27a65ccaa1..16153d48ce 100644 --- a/pkg/kn/commands/source/apiserver/delete.go +++ b/pkg/kn/commands/source/apiserver/delete.go @@ -26,13 +26,13 @@ import ( func NewApiServerDeleteCommand(p *commands.KnParams) *cobra.Command { ApiServerDeleteCommand := &cobra.Command{ Use: "delete NAME", - Short: "Delete an ApiServerSource.", + Short: "Delete an ApiServer source.", Example: ` # Delete an ApiServerSource 'k8sevents' in default namespace kn source apiserver delete k8sevents`, RunE: func(cmd *cobra.Command, args []string) error { if len(args) != 1 { - return errors.New("'source apiserver delete' requires the name of the source as single argument") + return errors.New("requires the name of the source as single argument") } name := args[0] diff --git a/pkg/kn/commands/source/apiserver/update.go b/pkg/kn/commands/source/apiserver/update.go index 8e7c42647d..542a2f2ad4 100644 --- a/pkg/kn/commands/source/apiserver/update.go +++ b/pkg/kn/commands/source/apiserver/update.go @@ -31,7 +31,7 @@ func NewApiServerUpdateCommand(p *commands.KnParams) *cobra.Command { cmd := &cobra.Command{ Use: "update NAME --resource RESOURCE --service-account ACCOUNTNAME --sink SINK --mode MODE", - Short: "Update an ApiServerSource, which watches for Kubernetes events and forwards them to a sink", + Short: "Update an ApiServerSource.", Example: ` # Update an ApiServerSource 'k8sevents' with different service account and sink service kn source apiserver update k8sevents --service-account newsa --sink svc:newsvc`, From 101e627ef94e2ccc6fc99fd19c0d6f920a4571fa Mon Sep 17 00:00:00 2001 From: Navid Shaikh Date: Mon, 16 Dec 2019 17:16:30 +0530 Subject: [PATCH 12/16] Add unit tests for get/create/update/delete in apiserver_client.go --- .../sources/v1alpha1/apiserver_client_test.go | 125 +++++++++++------- 1 file changed, 78 insertions(+), 47 deletions(-) diff --git a/pkg/eventing/sources/v1alpha1/apiserver_client_test.go b/pkg/eventing/sources/v1alpha1/apiserver_client_test.go index ce95e32cfa..8b76851499 100644 --- a/pkg/eventing/sources/v1alpha1/apiserver_client_test.go +++ b/pkg/eventing/sources/v1alpha1/apiserver_client_test.go @@ -19,86 +19,117 @@ import ( "testing" "gotest.tools/assert" + v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" client_testing "k8s.io/client-go/testing" "knative.dev/eventing/pkg/apis/sources/v1alpha1" "knative.dev/eventing/pkg/client/clientset/versioned/typed/sources/v1alpha1/fake" + "knative.dev/pkg/apis/duck/v1beta1" ) var testApiServerSourceNamespace = "test-ns" -func setupApiServerSourcesClient() (fakeSources fake.FakeSourcesV1alpha1, client KnApiServerSourcesClient) { +func setupApiServerSourcesClient(t *testing.T) (fakeSources fake.FakeSourcesV1alpha1, client KnApiServerSourcesClient) { fakeSources = fake.FakeSourcesV1alpha1{Fake: &client_testing.Fake{}} client = NewKnSourcesClient(&fakeSources, testApiServerSourceNamespace).ApiServerSourcesClient() + assert.Equal(t, client.Namespace(), testApiServerSourceNamespace) return } func TestDeleteApiServerSource(t *testing.T) { - var srcName = "new-src" - sourcesServer, client := setupApiServerSourcesClient() + sourcesServer, client := setupApiServerSourcesClient(t) - apisourceNew := newApiServerSource(srcName) - - sourcesServer.AddReactor("create", "apiserversources", + sourcesServer.AddReactor("delete", "apiserversources", func(a client_testing.Action) (bool, runtime.Object, error) { - assert.Equal(t, testApiServerSourceNamespace, a.GetNamespace()) - name := a.(client_testing.CreateAction).GetObject().(metav1.Object).GetName() - if name == apisourceNew.Name { - apisourceNew.Generation = 2 - return true, apisourceNew, nil + name := a.(client_testing.DeleteAction).GetName() + if name == "errorSource" { + return true, nil, fmt.Errorf("error while deleting ApiServer source %s", name) } - return true, nil, fmt.Errorf("error while creating apiserversource %s", name) + return true, nil, nil }) - t.Run("create apiserversource without error", func(t *testing.T) { - err := client.CreateApiServerSource(apisourceNew) - assert.NilError(t, err) - }) + err := client.DeleteApiServerSource("foo") + assert.NilError(t, err) - t.Run("create apiserversource with an error returns an error object", func(t *testing.T) { - err := client.CreateApiServerSource(newApiServerSource("unknown")) - assert.ErrorContains(t, err, "unknown") - }) + err = client.DeleteApiServerSource("errorSource") + assert.ErrorContains(t, err, "errorSource") } func TestCreateApiServerSource(t *testing.T) { - var srcName = "new-src" - sourcesServer, client := setupApiServerSourcesClient() - - apisourceNew := newApiServerSource(srcName) + sourcesServer, client := setupApiServerSourcesClient(t) sourcesServer.AddReactor("create", "apiserversources", func(a client_testing.Action) (bool, runtime.Object, error) { - assert.Equal(t, testApiServerSourceNamespace, a.GetNamespace()) - name := a.(client_testing.CreateAction).GetObject().(metav1.Object).GetName() - if name == apisourceNew.Name { - apisourceNew.Generation = 2 - return true, apisourceNew, nil + newSource := a.(client_testing.CreateAction).GetObject() + name := newSource.(metav1.Object).GetName() + if name == "errorSource" { + return true, nil, fmt.Errorf("error while creating ApiServer source %s", name) } - return true, nil, fmt.Errorf("error while creating apiserversource %s", name) + return true, newSource, nil }) + err := client.CreateApiServerSource(newApiServerSource("foo", "Event")) + assert.NilError(t, err) - t.Run("create apiserversource without error", func(t *testing.T) { - err := client.CreateApiServerSource(apisourceNew) - assert.NilError(t, err) - }) + err = client.CreateApiServerSource(newApiServerSource("errorSource", "Event")) + assert.ErrorContains(t, err, "errorSource") + +} + +func TestGetApiServerSource(t *testing.T) { + sourcesServer, client := setupApiServerSourcesClient(t) + + sourcesServer.AddReactor("get", "apiserversources", + func(a client_testing.Action) (bool, runtime.Object, error) { + name := a.(client_testing.GetAction).GetName() + if name == "errorSource" { + return true, nil, fmt.Errorf("error while getting ApiServer source %s", name) + } + return true, newApiServerSource(name, "Event"), nil + }) + testsource, err := client.GetApiServerSource("foo") + assert.NilError(t, err) + assert.Equal(t, testsource.Name, "foo") + assert.Equal(t, testsource.Spec.Sink.Ref.Name, "foosvc") + + _, err = client.GetApiServerSource("errorSource") + assert.ErrorContains(t, err, "errorSource") +} + +func TestUpdateApiServerSource(t *testing.T) { + sourcesServer, client := setupApiServerSourcesClient(t) + + sourcesServer.AddReactor("update", "apiserversources", + func(a client_testing.Action) (bool, runtime.Object, error) { + updatedSource := a.(client_testing.UpdateAction).GetObject() + name := updatedSource.(metav1.Object).GetName() + if name == "errorSource" { + return true, nil, fmt.Errorf("error while updating ApiServer source %s", name) + } + return true, NewAPIServerSourceBuilderFromExisting(updatedSource.(*v1alpha1.ApiServerSource)).Build(), nil + }) + err := client.UpdateApiServerSource(newApiServerSource("foo", "Event")) + assert.NilError(t, err) - t.Run("create apiserversource with an error returns an error object", func(t *testing.T) { - err := client.CreateApiServerSource(newApiServerSource("unknown")) - assert.ErrorContains(t, err, "unknown") - }) + err = client.UpdateApiServerSource(newApiServerSource("errorSource", "Event")) + assert.ErrorContains(t, err, "errorSource") } -func newApiServerSource(name string) *v1alpha1.ApiServerSource { - src := &v1alpha1.ApiServerSource{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: testApiServerSourceNamespace, - }, +func newApiServerSource(name, resource string) *v1alpha1.ApiServerSource { + b := NewAPIServerSourceBuilder(name).ServiceAccount("testsa").Mode("Ref") + b.Sink(&v1beta1.Destination{ + Ref: &v1.ObjectReference{ + Kind: "Service", + Name: "foosvc", + }}) + + if resource != "" { + b.Resources([]v1alpha1.ApiServerResource{{ + APIVersion: "v1", + Kind: resource, + Controller: false, + }}) } - src.Name = name - src.Namespace = testApiServerSourceNamespace - return src + return b.Build() } From 7a2e3d32617b8a6eca7d4616ef76c1aa0831d415 Mon Sep 17 00:00:00 2001 From: Navid Shaikh Date: Mon, 16 Dec 2019 17:24:51 +0530 Subject: [PATCH 13/16] Update e2e tests expected output per change in commands output --- test/e2e/source_apiserver_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/e2e/source_apiserver_test.go b/test/e2e/source_apiserver_test.go index 48a98e82b6..3b6b4519e1 100644 --- a/test/e2e/source_apiserver_test.go +++ b/test/e2e/source_apiserver_test.go @@ -64,7 +64,7 @@ func (test *e2eTest) apiServerSourceCreate(t *testing.T, sourceName string, reso out, err := test.kn.RunWithOpts([]string{"source", "apiserver", "create", sourceName, "--resource", resources, "--service-account", sa, "--sink", sink}, runOpts{NoNamespace: false}) assert.NilError(t, err) - assert.Check(t, util.ContainsAllIgnoreCase(out, "ApiServerSource", sourceName, "created", "namespace", test.kn.namespace)) + assert.Check(t, util.ContainsAllIgnoreCase(out, "apiserver", "source", sourceName, "created", "namespace", test.kn.namespace)) } func (test *e2eTest) apiServerSourceCreateMissingSink(t *testing.T, sourceName string, resources string, sa string, sink string) { @@ -76,7 +76,7 @@ func (test *e2eTest) apiServerSourceCreateMissingSink(t *testing.T, sourceName s func (test *e2eTest) apiServerSourceDelete(t *testing.T, sourceName string) { out, err := test.kn.RunWithOpts([]string{"source", "apiserver", "delete", sourceName}, runOpts{NoNamespace: false}) assert.NilError(t, err) - assert.Check(t, util.ContainsAllIgnoreCase(out, "ApiServerSource", sourceName, "deleted", "namespace", test.kn.namespace)) + assert.Check(t, util.ContainsAllIgnoreCase(out, "apiserver", "source", sourceName, "deleted", "namespace", test.kn.namespace)) } func (test *e2eTest) setupServiceAccountForApiserver(t *testing.T, name string) { From da7ceef68e5165a27f948b21518386e090c993e9 Mon Sep 17 00:00:00 2001 From: Navid Shaikh Date: Mon, 16 Dec 2019 19:43:11 +0530 Subject: [PATCH 14/16] Golint fixes, Api -> API and add exported method docs --- .../sources/v1alpha1/apiserver_client.go | 39 ++++++----- .../sources/v1alpha1/apiserver_client_mock.go | 67 ++++++++++--------- .../v1alpha1/apiserver_client_mock_test.go | 20 +++--- .../sources/v1alpha1/apiserver_client_test.go | 36 +++++----- pkg/eventing/sources/v1alpha1/client.go | 10 +-- pkg/kn/commands/source/apiserver/apiserver.go | 15 +++-- .../source/apiserver/apiserver_test.go | 12 ++-- pkg/kn/commands/source/apiserver/create.go | 18 ++--- .../source/apiserver/create_flag_test.go | 22 +++--- .../commands/source/apiserver/create_test.go | 10 +-- pkg/kn/commands/source/apiserver/delete.go | 16 ++--- .../commands/source/apiserver/delete_test.go | 12 ++-- pkg/kn/commands/source/apiserver/flags.go | 18 ++--- pkg/kn/commands/source/apiserver/update.go | 14 ++-- .../commands/source/apiserver/update_test.go | 12 ++-- pkg/kn/commands/source/source.go | 2 +- pkg/kn/commands/types_test.go | 2 +- 17 files changed, 167 insertions(+), 158 deletions(-) diff --git a/pkg/eventing/sources/v1alpha1/apiserver_client.go b/pkg/eventing/sources/v1alpha1/apiserver_client.go index 1f6154b9bd..0551690a11 100644 --- a/pkg/eventing/sources/v1alpha1/apiserver_client.go +++ b/pkg/eventing/sources/v1alpha1/apiserver_client.go @@ -22,20 +22,20 @@ import ( duckv1beta1 "knative.dev/pkg/apis/duck/v1beta1" ) -// Interface for working with ApiServer sources -type KnApiServerSourcesClient interface { +// KnAPIServerSourcesClient interface for working with ApiServer sources +type KnAPIServerSourcesClient interface { // Get an ApiServerSource by name - GetApiServerSource(name string) (*v1alpha1.ApiServerSource, error) + GetAPIServerSource(name string) (*v1alpha1.ApiServerSource, error) // Create an ApiServerSource by object - CreateApiServerSource(apiSource *v1alpha1.ApiServerSource) error + CreateAPIServerSource(apiSource *v1alpha1.ApiServerSource) error // Update an ApiServerSource by object - UpdateApiServerSource(apiSource *v1alpha1.ApiServerSource) error + UpdateAPIServerSource(apiSource *v1alpha1.ApiServerSource) error // Delete an ApiServerSource by name - DeleteApiServerSource(name string) error + DeleteAPIServerSource(name string) error // Get namespace for this client Namespace() string @@ -49,16 +49,16 @@ type apiServerSourcesClient struct { namespace string } -// NewKnSourcesClient is to invoke Eventing Sources Client API to create object -func newKnApiServerSourcesClient(client client_v1alpha1.ApiServerSourceInterface, namespace string) KnApiServerSourcesClient { +// newKnAPIServerSourcesClient is to invoke Eventing Sources Client API to create object +func newKnAPIServerSourcesClient(client client_v1alpha1.ApiServerSourceInterface, namespace string) KnAPIServerSourcesClient { return &apiServerSourcesClient{ client: client, namespace: namespace, } } -//GetApiServerSource returns apiSource object if present -func (c *apiServerSourcesClient) GetApiServerSource(name string) (*v1alpha1.ApiServerSource, error) { +//GetAPIServerSource returns apiSource object if present +func (c *apiServerSourcesClient) GetAPIServerSource(name string) (*v1alpha1.ApiServerSource, error) { apiSource, err := c.client.Get(name, metav1.GetOptions{}) if err != nil { return nil, kn_errors.GetError(err) @@ -67,8 +67,8 @@ func (c *apiServerSourcesClient) GetApiServerSource(name string) (*v1alpha1.ApiS return apiSource, nil } -//CreateApiServerSource is used to create an instance of ApiServerSource -func (c *apiServerSourcesClient) CreateApiServerSource(apiSource *v1alpha1.ApiServerSource) error { +//CreateAPIServerSource is used to create an instance of ApiServerSource +func (c *apiServerSourcesClient) CreateAPIServerSource(apiSource *v1alpha1.ApiServerSource) error { _, err := c.client.Create(apiSource) if err != nil { return kn_errors.GetError(err) @@ -77,8 +77,8 @@ func (c *apiServerSourcesClient) CreateApiServerSource(apiSource *v1alpha1.ApiSe return nil } -//UpdateApiServerSource is used to update an instance of ApiServerSource -func (c *apiServerSourcesClient) UpdateApiServerSource(apiSource *v1alpha1.ApiServerSource) error { +//UpdateAPIServerSource is used to update an instance of ApiServerSource +func (c *apiServerSourcesClient) UpdateAPIServerSource(apiSource *v1alpha1.ApiServerSource) error { _, err := c.client.Update(apiSource) if err != nil { return kn_errors.GetError(err) @@ -87,8 +87,8 @@ func (c *apiServerSourcesClient) UpdateApiServerSource(apiSource *v1alpha1.ApiSe return nil } -//DeleteApiServerSource is used to create an instance of ApiServerSource -func (c *apiServerSourcesClient) DeleteApiServerSource(name string) error { +//DeleteAPIServerSource is used to create an instance of ApiServerSource +func (c *apiServerSourcesClient) DeleteAPIServerSource(name string) error { err := c.client.Delete(name, &metav1.DeleteOptions{}) return err } @@ -103,6 +103,7 @@ type APIServerSourceBuilder struct { apiServerSource *v1alpha1.ApiServerSource } +// NewAPIServerSourceBuilder for building ApiServer source object func NewAPIServerSourceBuilder(name string) *APIServerSourceBuilder { return &APIServerSourceBuilder{apiServerSource: &v1alpha1.ApiServerSource{ ObjectMeta: metav1.ObjectMeta{ @@ -111,30 +112,36 @@ func NewAPIServerSourceBuilder(name string) *APIServerSourceBuilder { }} } +// NewAPIServerSourceBuilderFromExisting for building the object from existing ApiServerSource object func NewAPIServerSourceBuilderFromExisting(apiServerSource *v1alpha1.ApiServerSource) *APIServerSourceBuilder { return &APIServerSourceBuilder{apiServerSource: apiServerSource.DeepCopy()} } +// Resources which should be streamed func (b *APIServerSourceBuilder) Resources(resources []v1alpha1.ApiServerResource) *APIServerSourceBuilder { b.apiServerSource.Spec.Resources = resources return b } +// ServiceAccount with which this source should operate func (b *APIServerSourceBuilder) ServiceAccount(sa string) *APIServerSourceBuilder { b.apiServerSource.Spec.ServiceAccountName = sa return b } +// Mode for whether to send resource 'Ref' or complete 'Resource' func (b *APIServerSourceBuilder) Mode(mode string) *APIServerSourceBuilder { b.apiServerSource.Spec.Mode = mode return b } +// Sink or destination of the source func (b *APIServerSourceBuilder) Sink(sink *duckv1beta1.Destination) *APIServerSourceBuilder { b.apiServerSource.Spec.Sink = sink return b } +// Build the ApiServerSource object func (b *APIServerSourceBuilder) Build() *v1alpha1.ApiServerSource { return b.apiServerSource } diff --git a/pkg/eventing/sources/v1alpha1/apiserver_client_mock.go b/pkg/eventing/sources/v1alpha1/apiserver_client_mock.go index be0d9153cc..4ef573e052 100644 --- a/pkg/eventing/sources/v1alpha1/apiserver_client_mock.go +++ b/pkg/eventing/sources/v1alpha1/apiserver_client_mock.go @@ -22,87 +22,88 @@ import ( "knative.dev/client/pkg/util/mock" ) -type MockKnApiServerSourceClient struct { +// MockKnAPIServerSourceClient for mocking the client +type MockKnAPIServerSourceClient struct { t *testing.T - recorder *ApiServerSourcesRecorder + recorder *APIServerSourcesRecorder namespace string } -// NewMockKnApiServerSourceClient returns a new mock instance which you need to record for -func NewMockKnApiServerSourceClient(t *testing.T, ns ...string) *MockKnApiServerSourceClient { +// NewMockKnAPIServerSourceClient returns a new mock instance which you need to record for +func NewMockKnAPIServerSourceClient(t *testing.T, ns ...string) *MockKnAPIServerSourceClient { namespace := "default" if len(ns) > 0 { namespace = ns[0] } - return &MockKnApiServerSourceClient{ + return &MockKnAPIServerSourceClient{ t: t, - recorder: &ApiServerSourcesRecorder{mock.NewRecorder(t, namespace)}, + recorder: &APIServerSourcesRecorder{mock.NewRecorder(t, namespace)}, } } // Ensure that the interface is implemented -var _ KnApiServerSourcesClient = &MockKnApiServerSourceClient{} +var _ KnAPIServerSourcesClient = &MockKnAPIServerSourceClient{} -// recorder for service -type ApiServerSourcesRecorder struct { +// APIServerSourcesRecorder for recording actions on source +type APIServerSourcesRecorder struct { r *mock.Recorder } // Recorder returns the recorder for registering API calls -func (c *MockKnApiServerSourceClient) Recorder() *ApiServerSourcesRecorder { +func (c *MockKnAPIServerSourceClient) Recorder() *APIServerSourcesRecorder { return c.recorder } // Namespace of this client -func (c *MockKnApiServerSourceClient) Namespace() string { +func (c *MockKnAPIServerSourceClient) Namespace() string { return c.recorder.r.Namespace() } -// GetApiServerSource records a call for GetApiServerSource with the expected object or error. Either apiServerSource or err should be nil -func (sr *ApiServerSourcesRecorder) GetApiServerSource(name interface{}, apiServerSource *v1alpha1.ApiServerSource, err error) { +// GetAPIServerSource records a call for GetApiServerSource with the expected object or error. Either apiServerSource or err should be nil +func (sr *APIServerSourcesRecorder) GetAPIServerSource(name interface{}, apiServerSource *v1alpha1.ApiServerSource, err error) { sr.r.Add("GetApiServerSource", []interface{}{name}, []interface{}{apiServerSource, err}) } -// GetApiServerSource performs a previously recorded action, failing if non has been registered -func (c *MockKnApiServerSourceClient) GetApiServerSource(name string) (*v1alpha1.ApiServerSource, error) { +// GetAPIServerSource performs a previously recorded action, failing if non has been registered +func (c *MockKnAPIServerSourceClient) GetAPIServerSource(name string) (*v1alpha1.ApiServerSource, error) { call := c.recorder.r.VerifyCall("GetApiServerSource", name) return call.Result[0].(*v1alpha1.ApiServerSource), mock.ErrorOrNil(call.Result[1]) } -// CreateApiServerSource records a call for CreateApiServerSource with the expected error -func (sr *ApiServerSourcesRecorder) CreateApiServerSource(apiServerSource interface{}, err error) { +// CreateAPIServerSource records a call for CreateApiServerSource with the expected error +func (sr *APIServerSourcesRecorder) CreateAPIServerSource(apiServerSource interface{}, err error) { sr.r.Add("CreateApiServerSource", []interface{}{apiServerSource}, []interface{}{err}) } -// CreateApiServerSource performs a previously recorded action, failing if non has been registered -func (c *MockKnApiServerSourceClient) CreateApiServerSource(apiServerSource *v1alpha1.ApiServerSource) error { +// CreateAPIServerSource performs a previously recorded action, failing if non has been registered +func (c *MockKnAPIServerSourceClient) CreateAPIServerSource(apiServerSource *v1alpha1.ApiServerSource) error { call := c.recorder.r.VerifyCall("CreateApiServerSource", apiServerSource) return mock.ErrorOrNil(call.Result[0]) } -// UpdateApiServerSource records a call for UpdateApiServerSource with the expected error (nil if none) -func (sr *ApiServerSourcesRecorder) UpdateApiServerSource(apiServerSource interface{}, err error) { - sr.r.Add("UpdateApiServerSource", []interface{}{apiServerSource}, []interface{}{err}) +// UpdateAPIServerSource records a call for UpdateAPIServerSource with the expected error (nil if none) +func (sr *APIServerSourcesRecorder) UpdateAPIServerSource(apiServerSource interface{}, err error) { + sr.r.Add("UpdateAPIServerSource", []interface{}{apiServerSource}, []interface{}{err}) } -// UpdateApiServerSource performs a previously recorded action, failing if non has been registered -func (c *MockKnApiServerSourceClient) UpdateApiServerSource(apiServerSource *v1alpha1.ApiServerSource) error { - call := c.recorder.r.VerifyCall("UpdateApiServerSource", apiServerSource) +// UpdateAPIServerSource performs a previously recorded action, failing if non has been registered +func (c *MockKnAPIServerSourceClient) UpdateAPIServerSource(apiServerSource *v1alpha1.ApiServerSource) error { + call := c.recorder.r.VerifyCall("UpdateAPIServerSource", apiServerSource) return mock.ErrorOrNil(call.Result[0]) } -// UpdateApiServerSource records a call for DeleteApiServerSource with the expected error (nil if none) -func (sr *ApiServerSourcesRecorder) DeleteApiServerSource(name interface{}, err error) { - sr.r.Add("DeleteApiServerSource", []interface{}{name}, []interface{}{err}) +// DeleteAPIServerSource records a call for DeleteAPIServerSource with the expected error (nil if none) +func (sr *APIServerSourcesRecorder) DeleteAPIServerSource(name interface{}, err error) { + sr.r.Add("DeleteAPIServerSource", []interface{}{name}, []interface{}{err}) } -// DeleteApiServerSource performs a previously recorded action, failing if non has been registered -func (c *MockKnApiServerSourceClient) DeleteApiServerSource(name string) error { - call := c.recorder.r.VerifyCall("DeleteApiServerSource", name) +// DeleteAPIServerSource performs a previously recorded action, failing if non has been registered +func (c *MockKnAPIServerSourceClient) DeleteAPIServerSource(name string) error { + call := c.recorder.r.VerifyCall("DeleteAPIServerSource", name) return mock.ErrorOrNil(call.Result[0]) } -// Validates validates whether every recorded action has been called -func (sr *ApiServerSourcesRecorder) Validate() { +// Validate validates whether every recorded action has been called +func (sr *APIServerSourcesRecorder) Validate() { sr.r.CheckThatAllRecordedMethodsHaveBeenCalled() } diff --git a/pkg/eventing/sources/v1alpha1/apiserver_client_mock_test.go b/pkg/eventing/sources/v1alpha1/apiserver_client_mock_test.go index 9a0b5cd0e1..b7d68698d8 100644 --- a/pkg/eventing/sources/v1alpha1/apiserver_client_mock_test.go +++ b/pkg/eventing/sources/v1alpha1/apiserver_client_mock_test.go @@ -20,23 +20,23 @@ import ( "knative.dev/eventing/pkg/apis/sources/v1alpha1" ) -func TestMockKnApiServerSourceClient(t *testing.T) { +func TestMockKnAPIServerSourceClient(t *testing.T) { - client := NewMockKnApiServerSourceClient(t) + client := NewMockKnAPIServerSourceClient(t) recorder := client.Recorder() // Record all services - recorder.GetApiServerSource("hello", nil, nil) - recorder.CreateApiServerSource(&v1alpha1.ApiServerSource{}, nil) - recorder.UpdateApiServerSource(&v1alpha1.ApiServerSource{}, nil) - recorder.DeleteApiServerSource("hello", nil) + recorder.GetAPIServerSource("hello", nil, nil) + recorder.CreateAPIServerSource(&v1alpha1.ApiServerSource{}, nil) + recorder.UpdateAPIServerSource(&v1alpha1.ApiServerSource{}, nil) + recorder.DeleteAPIServerSource("hello", nil) // Call all service - client.GetApiServerSource("hello") - client.CreateApiServerSource(&v1alpha1.ApiServerSource{}) - client.UpdateApiServerSource(&v1alpha1.ApiServerSource{}) - client.DeleteApiServerSource("hello") + client.GetAPIServerSource("hello") + client.CreateAPIServerSource(&v1alpha1.ApiServerSource{}) + client.UpdateAPIServerSource(&v1alpha1.ApiServerSource{}) + client.DeleteAPIServerSource("hello") // Validate recorder.Validate() diff --git a/pkg/eventing/sources/v1alpha1/apiserver_client_test.go b/pkg/eventing/sources/v1alpha1/apiserver_client_test.go index 8b76851499..fd149d6b6b 100644 --- a/pkg/eventing/sources/v1alpha1/apiserver_client_test.go +++ b/pkg/eventing/sources/v1alpha1/apiserver_client_test.go @@ -29,17 +29,17 @@ import ( "knative.dev/pkg/apis/duck/v1beta1" ) -var testApiServerSourceNamespace = "test-ns" +var testAPIServerSourceNamespace = "test-ns" -func setupApiServerSourcesClient(t *testing.T) (fakeSources fake.FakeSourcesV1alpha1, client KnApiServerSourcesClient) { +func setupAPIServerSourcesClient(t *testing.T) (fakeSources fake.FakeSourcesV1alpha1, client KnAPIServerSourcesClient) { fakeSources = fake.FakeSourcesV1alpha1{Fake: &client_testing.Fake{}} - client = NewKnSourcesClient(&fakeSources, testApiServerSourceNamespace).ApiServerSourcesClient() - assert.Equal(t, client.Namespace(), testApiServerSourceNamespace) + client = NewKnSourcesClient(&fakeSources, testAPIServerSourceNamespace).APIServerSourcesClient() + assert.Equal(t, client.Namespace(), testAPIServerSourceNamespace) return } func TestDeleteApiServerSource(t *testing.T) { - sourcesServer, client := setupApiServerSourcesClient(t) + sourcesServer, client := setupAPIServerSourcesClient(t) sourcesServer.AddReactor("delete", "apiserversources", func(a client_testing.Action) (bool, runtime.Object, error) { @@ -50,15 +50,15 @@ func TestDeleteApiServerSource(t *testing.T) { return true, nil, nil }) - err := client.DeleteApiServerSource("foo") + err := client.DeleteAPIServerSource("foo") assert.NilError(t, err) - err = client.DeleteApiServerSource("errorSource") + err = client.DeleteAPIServerSource("errorSource") assert.ErrorContains(t, err, "errorSource") } func TestCreateApiServerSource(t *testing.T) { - sourcesServer, client := setupApiServerSourcesClient(t) + sourcesServer, client := setupAPIServerSourcesClient(t) sourcesServer.AddReactor("create", "apiserversources", func(a client_testing.Action) (bool, runtime.Object, error) { @@ -69,16 +69,16 @@ func TestCreateApiServerSource(t *testing.T) { } return true, newSource, nil }) - err := client.CreateApiServerSource(newApiServerSource("foo", "Event")) + err := client.CreateAPIServerSource(newAPIServerSource("foo", "Event")) assert.NilError(t, err) - err = client.CreateApiServerSource(newApiServerSource("errorSource", "Event")) + err = client.CreateAPIServerSource(newAPIServerSource("errorSource", "Event")) assert.ErrorContains(t, err, "errorSource") } func TestGetApiServerSource(t *testing.T) { - sourcesServer, client := setupApiServerSourcesClient(t) + sourcesServer, client := setupAPIServerSourcesClient(t) sourcesServer.AddReactor("get", "apiserversources", func(a client_testing.Action) (bool, runtime.Object, error) { @@ -86,19 +86,19 @@ func TestGetApiServerSource(t *testing.T) { if name == "errorSource" { return true, nil, fmt.Errorf("error while getting ApiServer source %s", name) } - return true, newApiServerSource(name, "Event"), nil + return true, newAPIServerSource(name, "Event"), nil }) - testsource, err := client.GetApiServerSource("foo") + testsource, err := client.GetAPIServerSource("foo") assert.NilError(t, err) assert.Equal(t, testsource.Name, "foo") assert.Equal(t, testsource.Spec.Sink.Ref.Name, "foosvc") - _, err = client.GetApiServerSource("errorSource") + _, err = client.GetAPIServerSource("errorSource") assert.ErrorContains(t, err, "errorSource") } func TestUpdateApiServerSource(t *testing.T) { - sourcesServer, client := setupApiServerSourcesClient(t) + sourcesServer, client := setupAPIServerSourcesClient(t) sourcesServer.AddReactor("update", "apiserversources", func(a client_testing.Action) (bool, runtime.Object, error) { @@ -109,14 +109,14 @@ func TestUpdateApiServerSource(t *testing.T) { } return true, NewAPIServerSourceBuilderFromExisting(updatedSource.(*v1alpha1.ApiServerSource)).Build(), nil }) - err := client.UpdateApiServerSource(newApiServerSource("foo", "Event")) + err := client.UpdateAPIServerSource(newAPIServerSource("foo", "Event")) assert.NilError(t, err) - err = client.UpdateApiServerSource(newApiServerSource("errorSource", "Event")) + err = client.UpdateAPIServerSource(newAPIServerSource("errorSource", "Event")) assert.ErrorContains(t, err, "errorSource") } -func newApiServerSource(name, resource string) *v1alpha1.ApiServerSource { +func newAPIServerSource(name, resource string) *v1alpha1.ApiServerSource { b := NewAPIServerSourceBuilder(name).ServiceAccount("testsa").Mode("Ref") b.Sink(&v1beta1.Destination{ Ref: &v1.ObjectReference{ diff --git a/pkg/eventing/sources/v1alpha1/client.go b/pkg/eventing/sources/v1alpha1/client.go index 74049199fc..f0c9b1cff5 100644 --- a/pkg/eventing/sources/v1alpha1/client.go +++ b/pkg/eventing/sources/v1alpha1/client.go @@ -22,7 +22,7 @@ import ( // namespace specified during construction type KnSourcesClient interface { // Get client for ApiServer sources - ApiServerSourcesClient() KnApiServerSourcesClient + APIServerSourcesClient() KnAPIServerSourcesClient // Get client for CronJob sources CronJobSourcesClient() KnCronJobSourcesClient @@ -36,7 +36,7 @@ type sourcesClient struct { namespace string } -// Create a new client for managing all eventing built-in sources +// NewKnSourcesClient for managing all eventing built-in sources func NewKnSourcesClient(client client_v1alpha1.SourcesV1alpha1Interface, namespace string) KnSourcesClient { return &sourcesClient{ client: client, @@ -44,9 +44,9 @@ func NewKnSourcesClient(client client_v1alpha1.SourcesV1alpha1Interface, namespa } } -// Get the client for dealing with apiserver sources -func (c *sourcesClient) ApiServerSourcesClient() KnApiServerSourcesClient { - return newKnApiServerSourcesClient(c.client.ApiServerSources(c.namespace), c.namespace) +// ApiServerSourcesClient for dealing with ApiServer sources +func (c *sourcesClient) APIServerSourcesClient() KnAPIServerSourcesClient { + return newKnAPIServerSourcesClient(c.client.ApiServerSources(c.namespace), c.namespace) } // Get the client for dealing with cronjob sources diff --git a/pkg/kn/commands/source/apiserver/apiserver.go b/pkg/kn/commands/source/apiserver/apiserver.go index 551014c487..f986d88f4a 100644 --- a/pkg/kn/commands/source/apiserver/apiserver.go +++ b/pkg/kn/commands/source/apiserver/apiserver.go @@ -24,20 +24,21 @@ import ( "knative.dev/client/pkg/kn/commands" ) -func NewApiServerCommand(p *commands.KnParams) *cobra.Command { +// NewAPIServerCommand for managing ApiServer source +func NewAPIServerCommand(p *commands.KnParams) *cobra.Command { apiServerSourceCmd := &cobra.Command{ Use: "apiserver", Short: "Kubernetes API Server Event Source command group", } - apiServerSourceCmd.AddCommand(NewApiServerCreateCommand(p)) - apiServerSourceCmd.AddCommand(NewApiServerUpdateCommand(p)) - apiServerSourceCmd.AddCommand(NewApiServerDeleteCommand(p)) + apiServerSourceCmd.AddCommand(NewAPIServerCreateCommand(p)) + apiServerSourceCmd.AddCommand(NewAPIServerUpdateCommand(p)) + apiServerSourceCmd.AddCommand(NewAPIServerDeleteCommand(p)) return apiServerSourceCmd } -var apiServerSourceClientFactory func(config clientcmd.ClientConfig, namespace string) (knsources_v1alpha1.KnApiServerSourcesClient, error) +var apiServerSourceClientFactory func(config clientcmd.ClientConfig, namespace string) (knsources_v1alpha1.KnAPIServerSourcesClient, error) -func newApiServerSourceClient(p *commands.KnParams, cmd *cobra.Command) (knsources_v1alpha1.KnApiServerSourcesClient, error) { +func newAPIServerSourceClient(p *commands.KnParams, cmd *cobra.Command) (knsources_v1alpha1.KnAPIServerSourcesClient, error) { namespace, err := p.GetNamespace(cmd) if err != nil { return nil, err @@ -61,5 +62,5 @@ func newApiServerSourceClient(p *commands.KnParams, cmd *cobra.Command) (knsourc return nil, err } - return knsources_v1alpha1.NewKnSourcesClient(client, namespace).ApiServerSourcesClient(), nil + return knsources_v1alpha1.NewKnSourcesClient(client, namespace).APIServerSourcesClient(), nil } diff --git a/pkg/kn/commands/source/apiserver/apiserver_test.go b/pkg/kn/commands/source/apiserver/apiserver_test.go index e260fcb162..09777f2472 100644 --- a/pkg/kn/commands/source/apiserver/apiserver_test.go +++ b/pkg/kn/commands/source/apiserver/apiserver_test.go @@ -55,7 +55,7 @@ current-context: x } } -func executeApiServerSourceCommand(apiServerSourceClient knsource_v1alpha1.KnApiServerSourcesClient, servingClient knserving_v1alpha1.KnServingClient, args ...string) (string, error) { +func executeAPIServerSourceCommand(apiServerSourceClient knsource_v1alpha1.KnAPIServerSourcesClient, servingClient knserving_v1alpha1.KnServingClient, args ...string) (string, error) { knParams := &commands.KnParams{} knParams.ClientConfig = blankConfig @@ -65,25 +65,25 @@ func executeApiServerSourceCommand(apiServerSourceClient knsource_v1alpha1.KnApi return servingClient, nil } - cmd := NewApiServerCommand(knParams) + cmd := NewAPIServerCommand(knParams) cmd.SetArgs(args) cmd.SetOutput(output) - apiServerSourceClientFactory = func(config clientcmd.ClientConfig, namespace string) (knsource_v1alpha1.KnApiServerSourcesClient, error) { + apiServerSourceClientFactory = func(config clientcmd.ClientConfig, namespace string) (knsource_v1alpha1.KnAPIServerSourcesClient, error) { return apiServerSourceClient, nil } - defer cleanupApiServerMockClient() + defer cleanupAPIServerMockClient() err := cmd.Execute() return output.String(), err } -func cleanupApiServerMockClient() { +func cleanupAPIServerMockClient() { apiServerSourceClientFactory = nil } -func createApiServerSource(name, resourceKind, resourceVersion, serviceAccount, mode, service string, isController bool) *v1alpha1.ApiServerSource { +func createAPIServerSource(name, resourceKind, resourceVersion, serviceAccount, mode, service string, isController bool) *v1alpha1.ApiServerSource { resources := []v1alpha1.ApiServerResource{{ APIVersion: resourceVersion, Kind: resourceKind, diff --git a/pkg/kn/commands/source/apiserver/create.go b/pkg/kn/commands/source/apiserver/create.go index 4c6300a05c..d34523246c 100644 --- a/pkg/kn/commands/source/apiserver/create.go +++ b/pkg/kn/commands/source/apiserver/create.go @@ -25,8 +25,9 @@ import ( "knative.dev/client/pkg/kn/commands/flags" ) -func NewApiServerCreateCommand(p *commands.KnParams) *cobra.Command { - var apiServerUpdateFlags ApiServerSourceUpdateFlags +// NewAPIServerCreateCommand for creating source +func NewAPIServerCreateCommand(p *commands.KnParams) *cobra.Command { + var updateFlags APIServerSourceUpdateFlags var sinkFlags flags.SinkFlags cmd := &cobra.Command{ @@ -43,7 +44,7 @@ func NewApiServerCreateCommand(p *commands.KnParams) *cobra.Command { name := args[0] // get client - apiSourceClient, err := newApiServerSourceClient(p, cmd) + apiSourceClient, err := newAPIServerSourceClient(p, cmd) if err != nil { return err } @@ -64,11 +65,11 @@ func NewApiServerCreateCommand(p *commands.KnParams) *cobra.Command { } // create - err = apiSourceClient.CreateApiServerSource( + err = apiSourceClient.CreateAPIServerSource( v1alpha1.NewAPIServerSourceBuilder(name). - Resources(apiServerUpdateFlags.GetApiServerResourceArray()). - ServiceAccount(apiServerUpdateFlags.ServiceAccountName). - Mode(apiServerUpdateFlags.Mode). + Resources(updateFlags.GetAPIServerResourceArray()). + ServiceAccount(updateFlags.ServiceAccountName). + Mode(updateFlags.Mode). Sink(objectRef). Build()) @@ -86,9 +87,8 @@ func NewApiServerCreateCommand(p *commands.KnParams) *cobra.Command { }, } commands.AddNamespaceFlags(cmd.Flags(), false) - apiServerUpdateFlags.Add(cmd) + updateFlags.Add(cmd) sinkFlags.Add(cmd) cmd.MarkFlagRequired("resource") - return cmd } diff --git a/pkg/kn/commands/source/apiserver/create_flag_test.go b/pkg/kn/commands/source/apiserver/create_flag_test.go index 3db94d9955..6cf9dff040 100644 --- a/pkg/kn/commands/source/apiserver/create_flag_test.go +++ b/pkg/kn/commands/source/apiserver/create_flag_test.go @@ -21,14 +21,14 @@ import ( sources_v1alpha1 "knative.dev/eventing/pkg/apis/sources/v1alpha1" ) -func TestGetApiServerResourceArray(t *testing.T) { +func TestGetAPIServerResourceArray(t *testing.T) { t.Run("get single apiserver resource", func(t *testing.T) { - createFlag := ApiServerSourceUpdateFlags{ + createFlag := APIServerSourceUpdateFlags{ ServiceAccountName: "test-sa", Mode: "Ref", Resources: []string{"Service:serving.knative.dev/v1alpha1:true"}, } - created := createFlag.GetApiServerResourceArray() + created := createFlag.GetAPIServerResourceArray() wanted := []sources_v1alpha1.ApiServerResource{{ APIVersion: "serving.knative.dev/v1alpha1", Kind: "Service", @@ -37,12 +37,12 @@ func TestGetApiServerResourceArray(t *testing.T) { assert.DeepEqual(t, wanted, created) // default isController - createFlag = ApiServerSourceUpdateFlags{ + createFlag = APIServerSourceUpdateFlags{ ServiceAccountName: "test-sa", Mode: "Ref", Resources: []string{"Service:serving.knative.dev/v1alpha1"}, } - created = createFlag.GetApiServerResourceArray() + created = createFlag.GetAPIServerResourceArray() wanted = []sources_v1alpha1.ApiServerResource{{ APIVersion: "serving.knative.dev/v1alpha1", Kind: "Service", @@ -51,12 +51,12 @@ func TestGetApiServerResourceArray(t *testing.T) { assert.DeepEqual(t, wanted, created) // default api version and isController - createFlag = ApiServerSourceUpdateFlags{ + createFlag = APIServerSourceUpdateFlags{ ServiceAccountName: "test-sa", Mode: "Ref", Resources: []string{"Service"}, } - created = createFlag.GetApiServerResourceArray() + created = createFlag.GetAPIServerResourceArray() wanted = []sources_v1alpha1.ApiServerResource{{ APIVersion: "v1", Kind: "Service", @@ -66,12 +66,12 @@ func TestGetApiServerResourceArray(t *testing.T) { }) t.Run("get multiple apiserver resources", func(t *testing.T) { - createFlag := ApiServerSourceUpdateFlags{ + createFlag := APIServerSourceUpdateFlags{ ServiceAccountName: "test-sa", Mode: "Resource", Resources: []string{"Event:v1:true", "Pod:v2:false"}, } - created := createFlag.GetApiServerResourceArray() + created := createFlag.GetAPIServerResourceArray() wanted := []sources_v1alpha1.ApiServerResource{{ APIVersion: "v1", Kind: "Event", @@ -84,12 +84,12 @@ func TestGetApiServerResourceArray(t *testing.T) { assert.DeepEqual(t, wanted, created) // default api version and isController - createFlag = ApiServerSourceUpdateFlags{ + createFlag = APIServerSourceUpdateFlags{ ServiceAccountName: "test-sa", Mode: "Resource", Resources: []string{"Event", "Pod"}, } - created = createFlag.GetApiServerResourceArray() + created = createFlag.GetAPIServerResourceArray() wanted = []sources_v1alpha1.ApiServerResource{{ APIVersion: "v1", diff --git a/pkg/kn/commands/source/apiserver/create_test.go b/pkg/kn/commands/source/apiserver/create_test.go index 17a6cc05b4..fb05be643a 100644 --- a/pkg/kn/commands/source/apiserver/create_test.go +++ b/pkg/kn/commands/source/apiserver/create_test.go @@ -28,7 +28,7 @@ import ( func TestCreateApiServerSource(t *testing.T) { - apiServerClient := knsources_v1alpha1.NewMockKnApiServerSourceClient(t) + apiServerClient := knsources_v1alpha1.NewMockKnAPIServerSourceClient(t) servingClient := knserving_client.NewMockKnServiceClient(t) servingRecorder := servingClient.Recorder() @@ -38,9 +38,9 @@ func TestCreateApiServerSource(t *testing.T) { }, nil) apiServerRecorder := apiServerClient.Recorder() - apiServerRecorder.CreateApiServerSource(createApiServerSource("testsource", "Event", "v1", "testsa", "Ref", "testsvc", false), nil) + apiServerRecorder.CreateAPIServerSource(createAPIServerSource("testsource", "Event", "v1", "testsa", "Ref", "testsvc", false), nil) - out, err := executeApiServerSourceCommand(apiServerClient, servingClient, "create", "testsource", "--resource", "Event:v1:false", "--service-account", "testsa", "--sink", "svc:testsvc", "--mode", "Ref") + out, err := executeAPIServerSourceCommand(apiServerClient, servingClient, "create", "testsource", "--resource", "Event:v1:false", "--service-account", "testsa", "--sink", "svc:testsvc", "--mode", "Ref") assert.NilError(t, err, "ApiServer source should be created") util.ContainsAll(out, "created", "default", "testsource") @@ -50,13 +50,13 @@ func TestCreateApiServerSource(t *testing.T) { func TestNoSinkError(t *testing.T) { servingClient := knserving_client.NewMockKnServiceClient(t) - apiServerClient := knsources_v1alpha1.NewMockKnApiServerSourceClient(t) + apiServerClient := knsources_v1alpha1.NewMockKnAPIServerSourceClient(t) errorMsg := "cannot create ApiServerSource 'testsource' in namespace 'default' because no Service svc found" servingRecorder := servingClient.Recorder() servingRecorder.GetService("testsvc", nil, errors.New("no Service svc found")) - out, err := executeApiServerSourceCommand(apiServerClient, servingClient, "create", "testsource", "--resource", "Event:v1:false", "--service-account", "testsa", "--sink", "svc:testsvc", "--mode", "Ref") + out, err := executeAPIServerSourceCommand(apiServerClient, servingClient, "create", "testsource", "--resource", "Event:v1:false", "--service-account", "testsa", "--sink", "svc:testsvc", "--mode", "Ref") assert.Error(t, err, errorMsg) assert.Assert(t, util.ContainsAll(out, errorMsg, "Usage")) servingRecorder.Validate() diff --git a/pkg/kn/commands/source/apiserver/delete.go b/pkg/kn/commands/source/apiserver/delete.go index 16153d48ce..1eb5a1580f 100644 --- a/pkg/kn/commands/source/apiserver/delete.go +++ b/pkg/kn/commands/source/apiserver/delete.go @@ -22,9 +22,9 @@ import ( "knative.dev/client/pkg/kn/commands" ) -// NewRevisionDeleteCommand represent 'revision delete' command -func NewApiServerDeleteCommand(p *commands.KnParams) *cobra.Command { - ApiServerDeleteCommand := &cobra.Command{ +// NewAPIServerDeleteCommand for deleting source +func NewAPIServerDeleteCommand(p *commands.KnParams) *cobra.Command { + deleteCommand := &cobra.Command{ Use: "delete NAME", Short: "Delete an ApiServer source.", Example: ` @@ -41,19 +41,19 @@ func NewApiServerDeleteCommand(p *commands.KnParams) *cobra.Command { return err } - apiSourceClient, err := newApiServerSourceClient(p, cmd) + apiSourceClient, err := newAPIServerSourceClient(p, cmd) if err != nil { return err } - err = apiSourceClient.DeleteApiServerSource(name) + err = apiSourceClient.DeleteAPIServerSource(name) if err != nil { return err } - fmt.Fprintf(cmd.OutOrStdout(), "ApiServerSource '%s' deleted in namespace '%s'.\n", args[0], namespace) + fmt.Fprintf(cmd.OutOrStdout(), "ApiServer source '%s' deleted in namespace '%s'.\n", args[0], namespace) return nil }, } - commands.AddNamespaceFlags(ApiServerDeleteCommand.Flags(), false) - return ApiServerDeleteCommand + commands.AddNamespaceFlags(deleteCommand.Flags(), false) + return deleteCommand } diff --git a/pkg/kn/commands/source/apiserver/delete_test.go b/pkg/kn/commands/source/apiserver/delete_test.go index 3dcea96cf5..5d23811491 100644 --- a/pkg/kn/commands/source/apiserver/delete_test.go +++ b/pkg/kn/commands/source/apiserver/delete_test.go @@ -26,12 +26,12 @@ import ( func TestApiServerSourceDelete(t *testing.T) { - apiServerClient := knsources_v1alpha1.NewMockKnApiServerSourceClient(t, "testns") + apiServerClient := knsources_v1alpha1.NewMockKnAPIServerSourceClient(t, "testns") apiServerRecorder := apiServerClient.Recorder() - apiServerRecorder.DeleteApiServerSource("testsource", nil) + apiServerRecorder.DeleteAPIServerSource("testsource", nil) - out, err := executeApiServerSourceCommand(apiServerClient, nil, "delete", "testsource") + out, err := executeAPIServerSourceCommand(apiServerClient, nil, "delete", "testsource") assert.NilError(t, err) util.ContainsAll(out, "deleted", "testns", "testsource") @@ -40,12 +40,12 @@ func TestApiServerSourceDelete(t *testing.T) { func TestDeleteWithError(t *testing.T) { - apiServerClient := knsources_v1alpha1.NewMockKnApiServerSourceClient(t, "mynamespace") + apiServerClient := knsources_v1alpha1.NewMockKnAPIServerSourceClient(t, "mynamespace") apiServerRecorder := apiServerClient.Recorder() - apiServerRecorder.DeleteApiServerSource("testsource", errors.New("apiserver source testsource not found")) + apiServerRecorder.DeleteAPIServerSource("testsource", errors.New("apiserver source testsource not found")) - out, err := executeApiServerSourceCommand(apiServerClient, nil, "delete", "testsource") + out, err := executeAPIServerSourceCommand(apiServerClient, nil, "delete", "testsource") assert.ErrorContains(t, err, "testsource") util.ContainsAll(out, "apiserver", "source", "testsource", "not found") diff --git a/pkg/kn/commands/source/apiserver/flags.go b/pkg/kn/commands/source/apiserver/flags.go index d4d92deb30..4617c2cef2 100644 --- a/pkg/kn/commands/source/apiserver/flags.go +++ b/pkg/kn/commands/source/apiserver/flags.go @@ -23,19 +23,19 @@ import ( ) const ( - ApiVersionSplitChar = ":" - DefaultApiVersion = "v1" + apiVersionSplitChar = ":" + defaultAPIVersion = "v1" ) -// ApiServerSourceUpdateFlags are flags for create and update a ApiServerSource -type ApiServerSourceUpdateFlags struct { +// APIServerSourceUpdateFlags are flags for create and update a ApiServerSource +type APIServerSourceUpdateFlags struct { ServiceAccountName string Mode string Resources []string } -// GetApiServerResourceArray is to return an array of ApiServerResource from a string. A sample is Event:v1:true,Pod:v2:false -func (f *ApiServerSourceUpdateFlags) GetApiServerResourceArray() []v1alpha1.ApiServerResource { +// GetAPIServerResourceArray is to return an array of ApiServerResource from a string. A sample is Event:v1:true,Pod:v2:false +func (f *APIServerSourceUpdateFlags) GetAPIServerResourceArray() []v1alpha1.ApiServerResource { var resourceList []v1alpha1.ApiServerResource for _, r := range f.Resources { version, kind, controller := getValidResource(r) @@ -50,11 +50,11 @@ func (f *ApiServerSourceUpdateFlags) GetApiServerResourceArray() []v1alpha1.ApiS } func getValidResource(resource string) (string, string, bool) { - var version = DefaultApiVersion // v1 as default + var version = defaultAPIVersion // v1 as default var isController = false //false as default var err error - parts := strings.Split(resource, ApiVersionSplitChar) + parts := strings.Split(resource, apiVersionSplitChar) kind := parts[0] if len(parts) >= 2 { version = parts[1] @@ -69,7 +69,7 @@ func getValidResource(resource string) (string, string, bool) { } //Add is to set parameters -func (f *ApiServerSourceUpdateFlags) Add(cmd *cobra.Command) { +func (f *APIServerSourceUpdateFlags) Add(cmd *cobra.Command) { cmd.Flags().StringVar(&f.ServiceAccountName, "service-account", "", diff --git a/pkg/kn/commands/source/apiserver/update.go b/pkg/kn/commands/source/apiserver/update.go index 542a2f2ad4..cfa1570421 100644 --- a/pkg/kn/commands/source/apiserver/update.go +++ b/pkg/kn/commands/source/apiserver/update.go @@ -25,8 +25,9 @@ import ( "knative.dev/client/pkg/kn/commands/flags" ) -func NewApiServerUpdateCommand(p *commands.KnParams) *cobra.Command { - var apiServerUpdateFlags ApiServerSourceUpdateFlags +// NewAPIServerUpdateCommand for managing source update +func NewAPIServerUpdateCommand(p *commands.KnParams) *cobra.Command { + var apiServerUpdateFlags APIServerSourceUpdateFlags var sinkFlags flags.SinkFlags cmd := &cobra.Command{ @@ -53,12 +54,12 @@ func NewApiServerUpdateCommand(p *commands.KnParams) *cobra.Command { return err } - sourcesClient, err := newApiServerSourceClient(p, cmd) + sourcesClient, err := newAPIServerSourceClient(p, cmd) if err != nil { return err } - source, err := sourcesClient.GetApiServerSource(name) + source, err := sourcesClient.GetAPIServerSource(name) if err != nil { return err } @@ -73,7 +74,7 @@ func NewApiServerUpdateCommand(p *commands.KnParams) *cobra.Command { } if cmd.Flags().Changed("resource") { - b.Resources(apiServerUpdateFlags.GetApiServerResourceArray()) + b.Resources(apiServerUpdateFlags.GetAPIServerResourceArray()) } if cmd.Flags().Changed("sink") { @@ -84,7 +85,7 @@ func NewApiServerUpdateCommand(p *commands.KnParams) *cobra.Command { b.Sink(objectRef) } - err = sourcesClient.UpdateApiServerSource(b.Build()) + err = sourcesClient.UpdateAPIServerSource(b.Build()) if err == nil { fmt.Fprintf(cmd.OutOrStdout(), "ApiServer source '%s' updated in namespace '%s'.\n", args[0], namespace) } @@ -95,6 +96,5 @@ func NewApiServerUpdateCommand(p *commands.KnParams) *cobra.Command { commands.AddNamespaceFlags(cmd.Flags(), false) apiServerUpdateFlags.Add(cmd) sinkFlags.Add(cmd) - return cmd } diff --git a/pkg/kn/commands/source/apiserver/update_test.go b/pkg/kn/commands/source/apiserver/update_test.go index 4eaf62033d..a8df007ad3 100644 --- a/pkg/kn/commands/source/apiserver/update_test.go +++ b/pkg/kn/commands/source/apiserver/update_test.go @@ -28,24 +28,24 @@ import ( ) func TestApiServerSourceUpdate(t *testing.T) { - apiServerClient := knsources_v1alpha1.NewMockKnApiServerSourceClient(t) + apiServerClient := knsources_v1alpha1.NewMockKnAPIServerSourceClient(t) servingClient := knserving_client.NewMockKnServiceClient(t) apiServerRecorder := apiServerClient.Recorder() servingRecorder := servingClient.Recorder() - present := createApiServerSource("testsource", "Event", "v1", "testsa1", "Ref", "svc1", false) - apiServerRecorder.GetApiServerSource("testsource", present, nil) + present := createAPIServerSource("testsource", "Event", "v1", "testsa1", "Ref", "svc1", false) + apiServerRecorder.GetAPIServerSource("testsource", present, nil) servingRecorder.GetService("svc2", &serving_v1alpha1.Service{ TypeMeta: metav1.TypeMeta{Kind: "Service"}, ObjectMeta: metav1.ObjectMeta{Name: "svc2"}, }, nil) - updated := createApiServerSource("testsource", "Event", "v1", "testsa2", "Ref", "svc2", false) - apiServerRecorder.UpdateApiServerSource(updated, nil) + updated := createAPIServerSource("testsource", "Event", "v1", "testsa2", "Ref", "svc2", false) + apiServerRecorder.UpdateAPIServerSource(updated, nil) - output, err := executeApiServerSourceCommand(apiServerClient, servingClient, "update", "testsource", "--service-account", "testsa2", "--sink", "svc:svc2") + output, err := executeAPIServerSourceCommand(apiServerClient, servingClient, "update", "testsource", "--service-account", "testsa2", "--sink", "svc:svc2") assert.NilError(t, err) assert.Assert(t, util.ContainsAll(output, "testsource", "updated", "default")) diff --git a/pkg/kn/commands/source/source.go b/pkg/kn/commands/source/source.go index 37c076291f..88e6c37843 100644 --- a/pkg/kn/commands/source/source.go +++ b/pkg/kn/commands/source/source.go @@ -27,7 +27,7 @@ func NewSourceCommand(p *commands.KnParams) *cobra.Command { Use: "source", Short: "Event source command group", } - sourceCmd.AddCommand(apiserver.NewApiServerCommand(p)) + sourceCmd.AddCommand(apiserver.NewAPIServerCommand(p)) sourceCmd.AddCommand(NewListTypesCommand(p)) sourceCmd.AddCommand(cronjob.NewCronJobCommand(p)) return sourceCmd diff --git a/pkg/kn/commands/types_test.go b/pkg/kn/commands/types_test.go index ca84cb057f..6457549990 100644 --- a/pkg/kn/commands/types_test.go +++ b/pkg/kn/commands/types_test.go @@ -187,7 +187,7 @@ func TestNewSourcesClient(t *testing.T) { } if sourcesClient != nil { - assert.Assert(t, sourcesClient.ApiServerSourcesClient().Namespace() == namespace) + assert.Assert(t, sourcesClient.APIServerSourcesClient().Namespace() == namespace) assert.Assert(t, sourcesClient.CronJobSourcesClient().Namespace() == namespace) } } From 1264b660f68c817cbc1249e5bb350c09b6395848 Mon Sep 17 00:00:00 2001 From: Navid Shaikh Date: Mon, 16 Dec 2019 19:56:36 +0530 Subject: [PATCH 15/16] Rename a test method and source update command description --- docs/cmd/kn_source_apiserver.md | 2 +- docs/cmd/kn_source_apiserver_update.md | 4 ++-- pkg/kn/commands/source/apiserver/update.go | 2 +- test/e2e/source_apiserver_test.go | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/cmd/kn_source_apiserver.md b/docs/cmd/kn_source_apiserver.md index 7348023f18..d57a7c1fe5 100644 --- a/docs/cmd/kn_source_apiserver.md +++ b/docs/cmd/kn_source_apiserver.md @@ -29,5 +29,5 @@ kn source apiserver [flags] * [kn source](kn_source.md) - Event source command group * [kn source apiserver create](kn_source_apiserver_create.md) - Create an ApiServer source. * [kn source apiserver delete](kn_source_apiserver_delete.md) - Delete an ApiServer source. -* [kn source apiserver update](kn_source_apiserver_update.md) - Update an ApiServerSource. +* [kn source apiserver update](kn_source_apiserver_update.md) - Update an ApiServer source. diff --git a/docs/cmd/kn_source_apiserver_update.md b/docs/cmd/kn_source_apiserver_update.md index b918d4d947..8b7747a35c 100644 --- a/docs/cmd/kn_source_apiserver_update.md +++ b/docs/cmd/kn_source_apiserver_update.md @@ -1,10 +1,10 @@ ## kn source apiserver update -Update an ApiServerSource. +Update an ApiServer source. ### Synopsis -Update an ApiServerSource. +Update an ApiServer source. ``` kn source apiserver update NAME --resource RESOURCE --service-account ACCOUNTNAME --sink SINK --mode MODE [flags] diff --git a/pkg/kn/commands/source/apiserver/update.go b/pkg/kn/commands/source/apiserver/update.go index cfa1570421..d24437ff07 100644 --- a/pkg/kn/commands/source/apiserver/update.go +++ b/pkg/kn/commands/source/apiserver/update.go @@ -32,7 +32,7 @@ func NewAPIServerUpdateCommand(p *commands.KnParams) *cobra.Command { cmd := &cobra.Command{ Use: "update NAME --resource RESOURCE --service-account ACCOUNTNAME --sink SINK --mode MODE", - Short: "Update an ApiServerSource.", + Short: "Update an ApiServer source.", Example: ` # Update an ApiServerSource 'k8sevents' with different service account and sink service kn source apiserver update k8sevents --service-account newsa --sink svc:newsvc`, diff --git a/test/e2e/source_apiserver_test.go b/test/e2e/source_apiserver_test.go index 3b6b4519e1..3cd8e9a578 100644 --- a/test/e2e/source_apiserver_test.go +++ b/test/e2e/source_apiserver_test.go @@ -53,7 +53,7 @@ func TestSourceApiServer(t *testing.T) { test.serviceCreate(t, "testsvc1") test.apiServerSourceUpdateSink(t, "testapisource3", "svc:testsvc1") jpSinkRefNameInSpec := "jsonpath={.spec.sink.ref.name}" - out, err := test.k8sGetResourceJsonPath(t, "apiserversource", "testapisource3", jpSinkRefNameInSpec) + out, err := test.getResourceFieldsWithJSONPath(t, "apiserversource", "testapisource3", jpSinkRefNameInSpec) assert.NilError(t, err) assert.Equal(t, out, "testsvc1") // TODO(navidshaikh): Verify the source's status with synchronous create/update @@ -102,7 +102,7 @@ func (test *e2eTest) apiServerSourceUpdateSink(t *testing.T, sourceName string, assert.Check(t, util.ContainsAll(out, sourceName, "updated", "namespace", test.kn.namespace)) } -func (test *e2eTest) k8sGetResourceJsonPath(t *testing.T, resource, name, jsonpath string) (string, error) { +func (test *e2eTest) getResourceFieldsWithJSONPath(t *testing.T, resource, name, jsonpath string) (string, error) { kubectl := kubectl{t, Logger{}} out, err := kubectl.RunWithOpts([]string{"get", resource, name, "-o", jsonpath, "-n", test.kn.namespace}, runOpts{}) if err != nil { From 3b747a726beccf48ea1cda08880700dcf41f9a7f Mon Sep 17 00:00:00 2001 From: Navid Shaikh Date: Mon, 16 Dec 2019 21:57:49 +0530 Subject: [PATCH 16/16] Add ApiServer source describe command - Add command and unit tests - TODO for later: Add 'Controller Selector' section for --verbose --- docs/cmd/kn_source_apiserver.md | 1 + docs/cmd/kn_source_apiserver_describe.md | 40 ++++++ pkg/kn/commands/source/apiserver/apiserver.go | 1 + pkg/kn/commands/source/apiserver/describe.go | 124 ++++++++++++++++++ .../source/apiserver/describe_test.go | 52 ++++++++ 5 files changed, 218 insertions(+) create mode 100644 docs/cmd/kn_source_apiserver_describe.md create mode 100644 pkg/kn/commands/source/apiserver/describe.go create mode 100644 pkg/kn/commands/source/apiserver/describe_test.go diff --git a/docs/cmd/kn_source_apiserver.md b/docs/cmd/kn_source_apiserver.md index d57a7c1fe5..29c9fba7d1 100644 --- a/docs/cmd/kn_source_apiserver.md +++ b/docs/cmd/kn_source_apiserver.md @@ -29,5 +29,6 @@ kn source apiserver [flags] * [kn source](kn_source.md) - Event source command group * [kn source apiserver create](kn_source_apiserver_create.md) - Create an ApiServer source. * [kn source apiserver delete](kn_source_apiserver_delete.md) - Delete an ApiServer source. +* [kn source apiserver describe](kn_source_apiserver_describe.md) - Describe an ApiServer source. * [kn source apiserver update](kn_source_apiserver_update.md) - Update an ApiServer source. diff --git a/docs/cmd/kn_source_apiserver_describe.md b/docs/cmd/kn_source_apiserver_describe.md new file mode 100644 index 0000000000..19cd923bf9 --- /dev/null +++ b/docs/cmd/kn_source_apiserver_describe.md @@ -0,0 +1,40 @@ +## kn source apiserver describe + +Describe an ApiServer source. + +### Synopsis + +Describe an ApiServer source. + +``` +kn source apiserver describe NAME [flags] +``` + +### Examples + +``` + + # Describe an ApiServer source with name 'k8sevents' + kn source apiserver describe k8sevents +``` + +### Options + +``` + -h, --help help for describe + -n, --namespace string Specify the namespace to operate in. + -v, --verbose More output. +``` + +### Options inherited from parent commands + +``` + --config string kn config file (default is $HOME/.kn/config.yaml) + --kubeconfig string kubectl config file (default is $HOME/.kube/config) + --log-http log http traffic +``` + +### SEE ALSO + +* [kn source apiserver](kn_source_apiserver.md) - Kubernetes API Server Event Source command group + diff --git a/pkg/kn/commands/source/apiserver/apiserver.go b/pkg/kn/commands/source/apiserver/apiserver.go index f986d88f4a..54b9f931ec 100644 --- a/pkg/kn/commands/source/apiserver/apiserver.go +++ b/pkg/kn/commands/source/apiserver/apiserver.go @@ -32,6 +32,7 @@ func NewAPIServerCommand(p *commands.KnParams) *cobra.Command { } apiServerSourceCmd.AddCommand(NewAPIServerCreateCommand(p)) apiServerSourceCmd.AddCommand(NewAPIServerUpdateCommand(p)) + apiServerSourceCmd.AddCommand(NewAPIServerDescribeCommand(p)) apiServerSourceCmd.AddCommand(NewAPIServerDeleteCommand(p)) return apiServerSourceCmd } diff --git a/pkg/kn/commands/source/apiserver/describe.go b/pkg/kn/commands/source/apiserver/describe.go new file mode 100644 index 0000000000..f90eacdf57 --- /dev/null +++ b/pkg/kn/commands/source/apiserver/describe.go @@ -0,0 +1,124 @@ +// Copyright © 2019 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 implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package apiserver + +import ( + "errors" + "fmt" + "strconv" + + "github.com/spf13/cobra" + "knative.dev/eventing/pkg/apis/sources/v1alpha1" + duckv1beta1 "knative.dev/pkg/apis/duck/v1beta1" + + "knative.dev/client/pkg/kn/commands" + "knative.dev/client/pkg/printers" +) + +// NewAPIServerDescribeCommand to describe an ApiServer source object +func NewAPIServerDescribeCommand(p *commands.KnParams) *cobra.Command { + + apiServerDescribe := &cobra.Command{ + Use: "describe NAME", + Short: "Describe an ApiServer source.", + Example: ` + # Describe an ApiServer source with name 'k8sevents' + kn source apiserver describe k8sevents`, + RunE: func(cmd *cobra.Command, args []string) error { + if len(args) != 1 { + return errors.New("requires the name of the source as single argument") + } + name := args[0] + + apiSourceClient, err := newAPIServerSourceClient(p, cmd) + if err != nil { + return err + } + + apiSource, err := apiSourceClient.GetAPIServerSource(name) + if err != nil { + return err + } + + out := cmd.OutOrStdout() + dw := printers.NewPrefixWriter(out) + + printDetails, err := cmd.Flags().GetBool("verbose") + if err != nil { + return err + } + + writeAPIServerSource(dw, apiSource, printDetails) + dw.WriteLine() + if err := dw.Flush(); err != nil { + return err + } + + writeSink(dw, apiSource.Spec.Sink) + dw.WriteLine() + if err := dw.Flush(); err != nil { + return err + } + + writeResources(dw, apiSource.Spec.Resources) + dw.WriteLine() + if err := dw.Flush(); err != nil { + return err + } + + // Condition info + commands.WriteConditions(dw, apiSource.Status.Conditions, printDetails) + if err := dw.Flush(); err != nil { + return err + } + + return nil + }, + } + flags := apiServerDescribe.Flags() + commands.AddNamespaceFlags(flags, false) + flags.BoolP("verbose", "v", false, "More output.") + + return apiServerDescribe +} + +func writeResources(dw printers.PrefixWriter, resources []v1alpha1.ApiServerResource) { + subWriter := dw.WriteAttribute("Resources", "") + for _, resource := range resources { + subWriter.WriteAttribute("Kind", fmt.Sprintf("%s (%s)", resource.Kind, resource.APIVersion)) + subWriter.WriteAttribute("Controller", strconv.FormatBool(resource.Controller)) + // TODO : Add Controller Selector section here for --verbose + } +} + +func writeSink(dw printers.PrefixWriter, sink *duckv1beta1.Destination) { + subWriter := dw.WriteAttribute("Sink", "") + subWriter.WriteAttribute("Name", sink.Ref.Name) + subWriter.WriteAttribute("Namespace", sink.Ref.Namespace) + ref := sink.Ref + if ref != nil { + subWriter.WriteAttribute("Kind", fmt.Sprintf("%s (%s)", sink.Ref.Kind, sink.Ref.APIVersion)) + } + uri := sink.URI + if uri != nil { + subWriter.WriteAttribute("URI", uri.String()) + } +} + +func writeAPIServerSource(dw printers.PrefixWriter, source *v1alpha1.ApiServerSource, printDetails bool) { + commands.WriteMetadata(dw, &source.ObjectMeta, printDetails) + dw.WriteAttribute("ServiceAccountName", source.Spec.ServiceAccountName) + dw.WriteAttribute("Mode", source.Spec.Mode) +} diff --git a/pkg/kn/commands/source/apiserver/describe_test.go b/pkg/kn/commands/source/apiserver/describe_test.go new file mode 100644 index 0000000000..6d8ed00cfa --- /dev/null +++ b/pkg/kn/commands/source/apiserver/describe_test.go @@ -0,0 +1,52 @@ +// Copyright © 2019 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 implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package apiserver + +import ( + "errors" + "testing" + + "gotest.tools/assert" + + knsource_v1alpha1 "knative.dev/client/pkg/eventing/sources/v1alpha1" + "knative.dev/client/pkg/util" +) + +func TestSimpleDescribe(t *testing.T) { + apiServerClient := knsource_v1alpha1.NewMockKnAPIServerSourceClient(t, "mynamespace") + + apiServerRecorder := apiServerClient.Recorder() + sampleSource := createAPIServerSource("testsource", "Event", "v1", "testsa", "Ref", "testsvc", false) + apiServerRecorder.GetAPIServerSource("testsource", sampleSource, nil) + + out, err := executeAPIServerSourceCommand(apiServerClient, nil, "describe", "testsource") + assert.NilError(t, err) + util.ContainsAll(out, "testsource", "testsa", "Ref", "testsvc", "Service", "Resources", "Event", "v1", "false", "Conditions") + + apiServerRecorder.Validate() +} + +func TestDescribeError(t *testing.T) { + apiServerClient := knsource_v1alpha1.NewMockKnAPIServerSourceClient(t, "mynamespace") + + apiServerRecorder := apiServerClient.Recorder() + apiServerRecorder.GetAPIServerSource("testsource", nil, errors.New("no apiserver source testsource")) + + out, err := executeAPIServerSourceCommand(apiServerClient, nil, "describe", "testsource") + assert.ErrorContains(t, err, "testsource") + util.ContainsAll(out, "Usage", "testsource") + + apiServerRecorder.Validate() +}