Skip to content

Commit

Permalink
add unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Daisy Guo committed Sep 22, 2020
1 parent 31e558a commit 9cd3071
Show file tree
Hide file tree
Showing 11 changed files with 1,048 additions and 362 deletions.
2 changes: 1 addition & 1 deletion pkg/kn/commands/source/container/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import (
func NewContainerSourceCommand(p *commands.KnParams) *cobra.Command {
containerSourceCmd := &cobra.Command{
Use: "container COMMAND",
Short: "Manage Kubernetes container sources",
Short: "Manage container sources",
}
containerSourceCmd.AddCommand(NewContainerCreateCommand(p))
containerSourceCmd.AddCommand(NewContainerDeleteCommand(p))
Expand Down
92 changes: 92 additions & 0 deletions pkg/kn/commands/source/container/container_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,95 @@ limitations under the License.
*/

package container

import (
"bytes"

corev1 "k8s.io/api/core/v1"
"k8s.io/client-go/tools/clientcmd"
v1alpha2 "knative.dev/eventing/pkg/apis/sources/v1alpha2"
duckv1 "knative.dev/pkg/apis/duck/v1"

kndynamic "knative.dev/client/pkg/dynamic"
clientv1alpha2 "knative.dev/client/pkg/sources/v1alpha2"

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

var blankConfig clientcmd.ClientConfig

// TODO: 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 executeContainerSourceCommand(containerSourceClient clientv1alpha2.KnContainerSourcesClient, dynamicClient kndynamic.KnDynamicClient, args ...string) (string, error) {
knParams := &commands.KnParams{}
knParams.ClientConfig = blankConfig

output := new(bytes.Buffer)
knParams.Output = output
knParams.NewDynamicClient = func(namespace string) (kndynamic.KnDynamicClient, error) {
return dynamicClient, nil
}

cmd := NewContainerSourceCommand(knParams)
cmd.SetArgs(args)
cmd.SetOutput(output)

containerSourceClientFactory = func(config clientcmd.ClientConfig, namespace string) (clientv1alpha2.KnContainerSourcesClient, error) {
return containerSourceClient, nil
}
defer cleanupContainerServerMockClient()

err := cmd.Execute()

return output.String(), err
}

func cleanupContainerServerMockClient() {
containerSourceClientFactory = nil
}

func createContainerSource(name, image string, sink duckv1.Destination) *v1alpha2.ContainerSource {
return clientv1alpha2.NewContainerSourceBuilder(name).
PodSpec(corev1.PodSpec{
Containers: []corev1.Container{{
Image: image,
Resources: corev1.ResourceRequirements{
Limits: corev1.ResourceList{},
Requests: corev1.ResourceList{},
},
}}}).
Sink(sink).
Build()
}

func createSinkv1(serviceName, namespace string) duckv1.Destination {
return duckv1.Destination{
Ref: &duckv1.KReference{
Kind: "Service",
Name: serviceName,
APIVersion: "serving.knative.dev/v1",
Namespace: namespace,
},
}
}
15 changes: 5 additions & 10 deletions pkg/kn/commands/source/container/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ import (
"knative.dev/client/pkg/kn/commands/flags"
knflags "knative.dev/client/pkg/kn/flags"

corev1 "k8s.io/api/core/v1"
"knative.dev/client/pkg/kn/commands"
"knative.dev/client/pkg/sources/v1alpha2"
eventingv2 "knative.dev/eventing/pkg/apis/sources/v1alpha2"
)

// NewContainerCreateCommand for creating source
Expand Down Expand Up @@ -59,29 +59,24 @@ func NewContainerCreateCommand(p *commands.KnParams) *cobra.Command {
if err != nil {
return err
}

objectRef, err := sinkFlags.ResolveSink(dynamicClient, namespace)
if err != nil {
return fmt.Errorf(
"cannot create ContainerSource '%s' in namespace '%s' "+
"because: %s", name, namespace, err)
}

var containerSource *eventingv2.ContainerSource
podSpec := containerSource.Spec.Template.Spec

err = podFlags.ResolvePodSpec(cmd, &podSpec)
podSpec := &corev1.PodSpec{Containers: []corev1.Container{{}}}
err = podFlags.ResolvePodSpec(podSpec, cmd)
if err != nil {
return fmt.Errorf(
"cannot create ContainerSource '%s' in namespace '%s' "+
"because: %s", name, namespace, err)
}

b := v1alpha2.NewContainerSourceBuilder(name).
PodSpec(podSpec).
Sink(*objectRef)

b := v1alpha2.NewContainerSourceBuilder(name).Sink(*objectRef).PodSpec(*podSpec)
err = srcClient.CreateContainerSource(b.Build())

if err != nil {
return fmt.Errorf(
"cannot create ContainerSource '%s' in namespace '%s' "+
Expand Down
45 changes: 45 additions & 0 deletions pkg/kn/commands/source/container/create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,48 @@ limitations under the License.
*/

package container

import (
"testing"

"gotest.tools/assert"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
servingv1 "knative.dev/serving/pkg/apis/serving/v1"

dynamicfake "knative.dev/client/pkg/dynamic/fake"
"knative.dev/client/pkg/sources/v1alpha2"
"knative.dev/client/pkg/util"
)

func TestCreateContainerSource(t *testing.T) {
testsvc := &servingv1.Service{
TypeMeta: metav1.TypeMeta{Kind: "Service", APIVersion: "serving.knative.dev/v1"},
ObjectMeta: metav1.ObjectMeta{Name: "testsvc", Namespace: "default"},
}
dynamicClient := dynamicfake.CreateFakeKnDynamicClient("default", testsvc)
containerClient := v1alpha2.NewMockKnContainerSourceClient(t)

containerRecorder := containerClient.Recorder()
containerRecorder.CreateContainerSource(createContainerSource("testsource", "docker.io/test/testimg", createSinkv1("testsvc", "default")), nil)

out, err := executeContainerSourceCommand(containerClient, dynamicClient, "create", "testsource", "--image", "docker.io/test/testimg", "--sink", "ksvc:testsvc")
assert.NilError(t, err, "Container source should be created")
assert.Assert(t, util.ContainsAll(out, "created", "default", "testsource"))

containerRecorder.Validate()
}

func TestSinkNotFoundError(t *testing.T) {
dynamicClient := dynamicfake.CreateFakeKnDynamicClient("default")
containerClient := v1alpha2.NewMockKnContainerSourceClient(t)
errorMsg := "cannot create ContainerSource 'testsource' in namespace 'default' because: services.serving.knative.dev \"testsvc\" not found"
out, err := executeContainerSourceCommand(containerClient, dynamicClient, "create", "testsource", "--image", "docker.io/test/testimg", "--sink", "ksvc:testsvc")
assert.Error(t, err, errorMsg)
assert.Assert(t, util.ContainsAll(out, errorMsg, "Usage"))
}

func TestNoSinkError(t *testing.T) {
containerClient := v1alpha2.NewMockKnContainerSourceClient(t)
_, err := executeContainerSourceCommand(containerClient, nil, "create", "testsource", "--image", "docker.io/test/testimg")
assert.ErrorContains(t, err, "required flag(s)", "sink", "not set")
}
38 changes: 38 additions & 0 deletions pkg/kn/commands/source/container/delete_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,41 @@ limitations under the License.
*/

package container

import (
"errors"
"testing"

"gotest.tools/assert"

"knative.dev/client/pkg/sources/v1alpha2"
"knative.dev/client/pkg/util"
)

func TestContainerSourceDelete(t *testing.T) {

containerClient := v1alpha2.NewMockKnContainerSourceClient(t, "testns")
containerRecorder := containerClient.Recorder()

containerRecorder.DeleteContainerSource("testsource", nil)

out, err := executeContainerSourceCommand(containerClient, nil, "delete", "testsource")
assert.NilError(t, err)
assert.Assert(t, util.ContainsAll(out, "deleted", "default", "testsource"))

containerRecorder.Validate()
}

func TestDeleteWithError(t *testing.T) {

containerClient := v1alpha2.NewMockKnContainerSourceClient(t, "mynamespace")
containerRecorder := containerClient.Recorder()

containerRecorder.DeleteContainerSource("testsource", errors.New("container source testsource not found"))

out, err := executeContainerSourceCommand(containerClient, nil, "delete", "testsource")
assert.ErrorContains(t, err, "testsource")
assert.Assert(t, util.ContainsAll(out, "container", "source", "testsource", "not found"))

containerRecorder.Validate()
}
42 changes: 41 additions & 1 deletion pkg/kn/flags/podspec.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"strings"

corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
"knative.dev/client/pkg/util"

"github.com/spf13/cobra"
Expand Down Expand Up @@ -170,7 +171,7 @@ func (p *PodSpecFlags) AddFlags(flagset *pflag.FlagSet) []string {
return flagNames
}

func (p *PodSpecFlags) ResolvePodSpec(cmd *cobra.Command, podSpec *corev1.PodSpec) error {
func (p *PodSpecFlags) ResolvePodSpec(podSpec *corev1.PodSpec, cmd *cobra.Command) error {
var err error

if cmd.Flags().Changed("env") {
Expand Down Expand Up @@ -243,6 +244,19 @@ func (p *PodSpecFlags) ResolvePodSpec(cmd *cobra.Command, podSpec *corev1.PodSpe
fmt.Fprintf(cmd.OutOrStdout(), "\nWARNING: flags --requests-cpu / --requests-memory are deprecated and going to be removed in future release, please use --request instead.\n\n")
}

limitsResources, err := p.computeResources(p.LimitsFlags)
if err != nil {
return err
}
requestsResources, err := p.computeResources(p.RequestsFlags)
if err != nil {
return err
}
err = UpdateResourcesDeprecated(podSpec, requestsResources, limitsResources)
if err != nil {
return err
}

requestsToRemove, limitsToRemove, err := p.Resources.Validate()
if err != nil {
return err
Expand Down Expand Up @@ -291,3 +305,29 @@ func (p *PodSpecFlags) ResolvePodSpec(cmd *cobra.Command, podSpec *corev1.PodSpe

return nil
}

func (p *PodSpecFlags) computeResources(resourceFlags ResourceFlags) (corev1.ResourceList, error) {
resourceList := corev1.ResourceList{}

if resourceFlags.CPU != "" {
cpuQuantity, err := resource.ParseQuantity(resourceFlags.CPU)
if err != nil {
return corev1.ResourceList{},
fmt.Errorf("Error parsing %q: %w", resourceFlags.CPU, err)
}

resourceList[corev1.ResourceCPU] = cpuQuantity
}

if resourceFlags.Memory != "" {
memoryQuantity, err := resource.ParseQuantity(resourceFlags.Memory)
if err != nil {
return corev1.ResourceList{},
fmt.Errorf("Error parsing %q: %w", resourceFlags.Memory, err)
}

resourceList[corev1.ResourceMemory] = memoryQuantity
}

return resourceList, nil
}
Loading

0 comments on commit 9cd3071

Please sign in to comment.