mirror of https://github.com/knative/client.git
Add ApiServer source update and describe commands (#556)
* 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. * Align creating ApiServer source client, removes unit tests * Add ApiServer source update command * Rename TestMockKnClient to TestMockKnCronJobSourceClient * Add mock client for ApiServer Source and its tests * Add mock unit tests for create, delete and update * 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 * Uses builder pattern for ApiServer source create command * Update ApiServer source create/update flags and required config * Uses builder pattern for ApiServer source update command * Align create/update/delete description and error messages * Add unit tests for get/create/update/delete in apiserver_client.go * Update e2e tests expected output per change in commands output * Golint fixes, Api -> API and add exported method docs * Rename a test method and source update command description * Add ApiServer source describe command - Add command and unit tests - TODO for later: Add 'Controller Selector' section for --verbose
This commit is contained in:
parent
7def9f49eb
commit
6ac25cdc00
|
|
@ -27,6 +27,8 @@ 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 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.
|
||||
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
@ -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
|
||||
```
|
||||
|
|
@ -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
|
||||
```
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
## kn source apiserver update
|
||||
|
||||
Update an ApiServer source.
|
||||
|
||||
### Synopsis
|
||||
|
||||
Update an ApiServer source.
|
||||
|
||||
```
|
||||
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
|
||||
|
||||
|
|
@ -15,21 +15,27 @@
|
|||
package v1alpha1
|
||||
|
||||
import (
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
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
|
||||
type KnApiServerSourcesClient interface {
|
||||
// KnAPIServerSourcesClient interface for working with ApiServer sources
|
||||
type KnAPIServerSourcesClient interface {
|
||||
|
||||
// Get an ApiServerSource by object
|
||||
CreateApiServerSource(apisvrsrc *v1alpha1.ApiServerSource) (*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
|
||||
DeleteAPIServerSource(name string) error
|
||||
|
||||
// Get namespace for this client
|
||||
Namespace() string
|
||||
|
|
@ -43,26 +49,47 @@ 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,
|
||||
}
|
||||
}
|
||||
|
||||
//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)
|
||||
//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 ins, nil
|
||||
|
||||
return apiSource, nil
|
||||
}
|
||||
|
||||
//DeleteApiServerSource is used to create an instance of ApiServerSource
|
||||
func (c *apiServerSourcesClient) DeleteApiServerSource(name string) error {
|
||||
err := c.client.Delete(name, &v1.DeleteOptions{})
|
||||
//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)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
//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
|
||||
}
|
||||
|
||||
|
|
@ -70,3 +97,51 @@ 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
|
||||
}
|
||||
|
||||
// NewAPIServerSourceBuilder for building ApiServer source object
|
||||
func NewAPIServerSourceBuilder(name string) *APIServerSourceBuilder {
|
||||
return &APIServerSourceBuilder{apiServerSource: &v1alpha1.ApiServerSource{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: name,
|
||||
},
|
||||
}}
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,109 @@
|
|||
// 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"
|
||||
)
|
||||
|
||||
// MockKnAPIServerSourceClient for mocking the client
|
||||
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{}
|
||||
|
||||
// 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 {
|
||||
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])
|
||||
}
|
||||
|
||||
// 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)
|
||||
return mock.ErrorOrNil(call.Result[0])
|
||||
}
|
||||
|
||||
// Validate validates whether every recorded action has been called
|
||||
func (sr *APIServerSourcesRecorder) Validate() {
|
||||
sr.r.CheckThatAllRecordedMethodsHaveBeenCalled()
|
||||
}
|
||||
|
|
@ -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()
|
||||
}
|
||||
|
|
@ -19,90 +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"
|
||||
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()
|
||||
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) {
|
||||
ins, err := client.CreateApiServerSource(apisourceNew)
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, ins.Name, srcName)
|
||||
assert.Equal(t, ins.Namespace, testApiServerSourceNamespace)
|
||||
})
|
||||
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) {
|
||||
ins, err := client.CreateApiServerSource(apisourceNew)
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, ins.Name, srcName)
|
||||
assert.Equal(t, ins.Namespace, testApiServerSourceNamespace)
|
||||
})
|
||||
err = client.CreateAPIServerSource(newAPIServerSource("errorSource", "Event"))
|
||||
assert.ErrorContains(t, err, "errorSource")
|
||||
|
||||
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")
|
||||
})
|
||||
}
|
||||
|
||||
func newApiServerSource(name string) *v1alpha1.ApiServerSource {
|
||||
src := &v1alpha1.ApiServerSource{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: name,
|
||||
Namespace: testApiServerSourceNamespace,
|
||||
},
|
||||
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)
|
||||
|
||||
err = client.UpdateAPIServerSource(newAPIServerSource("errorSource", "Event"))
|
||||
assert.ErrorContains(t, err, "errorSource")
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -16,16 +16,52 @@ 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"
|
||||
|
||||
knsources_v1alpha1 "knative.dev/client/pkg/eventing/sources/v1alpha1"
|
||||
"knative.dev/client/pkg/kn/commands"
|
||||
)
|
||||
|
||||
func NewApiServerCommand(p *commands.KnParams) *cobra.Command {
|
||||
apiServerImporterCmd := &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",
|
||||
}
|
||||
apiServerImporterCmd.AddCommand(NewApiServerCreateCommand(p))
|
||||
apiServerImporterCmd.AddCommand(NewApiServerDeleteCommand(p))
|
||||
return apiServerImporterCmd
|
||||
apiServerSourceCmd.AddCommand(NewAPIServerCreateCommand(p))
|
||||
apiServerSourceCmd.AddCommand(NewAPIServerUpdateCommand(p))
|
||||
apiServerSourceCmd.AddCommand(NewAPIServerDescribeCommand(p))
|
||||
apiServerSourceCmd.AddCommand(NewAPIServerDeleteCommand(p))
|
||||
return apiServerSourceCmd
|
||||
}
|
||||
|
||||
var apiServerSourceClientFactory func(config clientcmd.ClientConfig, namespace string) (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
|
||||
}
|
||||
|
||||
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 knsources_v1alpha1.NewKnSourcesClient(client, namespace).APIServerSourcesClient(), nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,105 @@
|
|||
// 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"
|
||||
"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 {
|
||||
resources := []v1alpha1.ApiServerResource{{
|
||||
APIVersion: resourceVersion,
|
||||
Kind: resourceKind,
|
||||
Controller: isController,
|
||||
}}
|
||||
|
||||
sink := &duckv1beta1.Destination{
|
||||
Ref: &corev1.ObjectReference{
|
||||
Kind: "Service",
|
||||
Name: service,
|
||||
}}
|
||||
|
||||
return knsource_v1alpha1.NewAPIServerSourceBuilder(name).
|
||||
Resources(resources).
|
||||
ServiceAccount(serviceAccount).
|
||||
Mode(mode).
|
||||
Sink(sink).
|
||||
Build()
|
||||
}
|
||||
|
|
@ -20,42 +20,38 @@ 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 {
|
||||
var apiServerUpdateFlags ApiServerSourceUpdateFlags
|
||||
// NewAPIServerCreateCommand for creating source
|
||||
func NewAPIServerCreateCommand(p *commands.KnParams) *cobra.Command {
|
||||
var updateFlags APIServerSourceUpdateFlags
|
||||
var sinkFlags flags.SinkFlags
|
||||
|
||||
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: `
|
||||
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("'source apiserver create' requires the name of the source as single argument")
|
||||
return errors.New("requires the name of the source to create as single argument")
|
||||
}
|
||||
name := args[0]
|
||||
|
||||
// get namespace
|
||||
namespace, err := p.GetNamespace(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// get client
|
||||
sourcesClient, err := p.NewSourcesClient(namespace)
|
||||
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,43 +64,31 @@ 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 = sourcesClient.ApiServerSourcesClient().CreateApiServerSource(apisrvsrc)
|
||||
err = apiSourceClient.CreateAPIServerSource(
|
||||
v1alpha1.NewAPIServerSourceBuilder(name).
|
||||
Resources(updateFlags.GetAPIServerResourceArray()).
|
||||
ServiceAccount(updateFlags.ServiceAccountName).
|
||||
Mode(updateFlags.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)
|
||||
apiServerUpdateFlags.Add(cmd)
|
||||
updateFlags.Add(cmd)
|
||||
sinkFlags.Add(cmd)
|
||||
cmd.MarkFlagRequired("schedule")
|
||||
|
||||
cmd.MarkFlagRequired("resource")
|
||||
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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -16,87 +16,48 @@ 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"
|
||||
knsources_v1alpha1 "knative.dev/client/pkg/eventing/sources/v1alpha1"
|
||||
knserving_client "knative.dev/client/pkg/serving/v1alpha1"
|
||||
"knative.dev/client/pkg/util"
|
||||
"knative.dev/eventing/pkg/apis/sources/v1alpha1"
|
||||
duckv1beta1 "knative.dev/pkg/apis/duck/v1beta1"
|
||||
serving_v1alpha1 "knative.dev/serving/pkg/apis/serving/v1alpha1"
|
||||
)
|
||||
|
||||
var (
|
||||
testApiServerSrcName = "foo"
|
||||
)
|
||||
func TestCreateApiServerSource(t *testing.T) {
|
||||
|
||||
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
|
||||
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 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)
|
||||
}
|
||||
func TestNoSinkError(t *testing.T) {
|
||||
servingClient := knserving_client.NewMockKnServiceClient(t)
|
||||
apiServerClient := knsources_v1alpha1.NewMockKnAPIServerSourceClient(t)
|
||||
|
||||
//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",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
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"))
|
||||
|
||||
//assert equal
|
||||
assert.DeepEqual(t, wanted, created)
|
||||
assert.Check(t, util.ContainsAll(output, "ApiServerSource", testApiServerSrcName, "created", "namespace", commands.FakeNamespace))
|
||||
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()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,17 +22,17 @@ 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 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]
|
||||
|
||||
|
|
@ -41,19 +41,19 @@ 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
|
||||
}
|
||||
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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,47 +15,39 @@
|
|||
package apiserver
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"gotest.tools/assert"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
client_testing "k8s.io/client-go/testing"
|
||||
"knative.dev/client/pkg/kn/commands"
|
||||
|
||||
knsources_v1alpha1 "knative.dev/client/pkg/eventing/sources/v1alpha1"
|
||||
"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 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 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))
|
||||
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()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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()
|
||||
}
|
||||
|
|
@ -19,27 +19,27 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
sources_v1alpha1 "knative.dev/eventing/pkg/apis/sources/v1alpha1"
|
||||
"knative.dev/eventing/pkg/apis/sources/v1alpha1"
|
||||
)
|
||||
|
||||
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() []sources_v1alpha1.ApiServerResource {
|
||||
var resourceList []sources_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)
|
||||
resourceRef := sources_v1alpha1.ApiServerResource{
|
||||
resourceRef := v1alpha1.ApiServerResource{
|
||||
APIVersion: version,
|
||||
Kind: kind,
|
||||
Controller: controller,
|
||||
|
|
@ -50,11 +50,11 @@ func (f *ApiServerSourceUpdateFlags) GetApiServerResourceArray() []sources_v1alp
|
|||
}
|
||||
|
||||
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",
|
||||
"",
|
||||
|
|
@ -85,5 +85,5 @@ 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.`)
|
||||
}
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
// 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/eventing/sources/v1alpha1"
|
||||
"knative.dev/client/pkg/kn/commands"
|
||||
"knative.dev/client/pkg/kn/commands/flags"
|
||||
)
|
||||
|
||||
// NewAPIServerUpdateCommand for managing source update
|
||||
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 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`,
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
servingClient, err := p.NewServingClient(namespace)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sourcesClient, err := newAPIServerSourceClient(p, cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
b.Sink(objectRef)
|
||||
}
|
||||
|
||||
err = sourcesClient.UpdateAPIServerSource(b.Build())
|
||||
if err == nil {
|
||||
fmt.Fprintf(cmd.OutOrStdout(), "ApiServer source '%s' updated in namespace '%s'.\n", args[0], namespace)
|
||||
}
|
||||
|
||||
return err
|
||||
},
|
||||
}
|
||||
commands.AddNamespaceFlags(cmd.Flags(), false)
|
||||
apiServerUpdateFlags.Add(cmd)
|
||||
sinkFlags.Add(cmd)
|
||||
return cmd
|
||||
}
|
||||
|
|
@ -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()
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.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
|
||||
})
|
||||
}
|
||||
|
||||
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, "apiserver", "source", 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, "apiserver", "source", 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) 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 {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue