Skip to content

Commit

Permalink
fix: Add specific reference resolution
Browse files Browse the repository at this point in the history
  • Loading branch information
dsimansk committed Mar 23, 2021
1 parent d310e95 commit df9c889
Show file tree
Hide file tree
Showing 7 changed files with 158 additions and 22 deletions.
2 changes: 1 addition & 1 deletion docs/cmd/kn_domain_create.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ kn domain create NAME
```
-h, --help help for create
-n, --namespace string Specify the namespace to operate in.
--ref string Addressable target reference for Domain Mapping. You can specify a Knative Service name.
--ref string Addressable target reference for Domain Mapping. You can specify a Knative service, a Knative soute or a Kubernetes service.Examples: '--ref ksvc:hello' or simply '--ref hello' for a Knative service 'hello', '--ref kroute:hello' for a Knative route 'hello', '--ref svc:hello' for a Kubernetes service 'hello'. If a prefix is not provided, it is considered as a Knative service.
```

### Options inherited from parent commands
Expand Down
4 changes: 2 additions & 2 deletions docs/cmd/kn_domain_update.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ kn domain update NAME
```
# Update a domain mappings 'hello.example.com' for Knative service 'hello'
kn domain create hello.example.com --ref hello
kn domain create hello.example.com --refFlags hello
```

### Options

```
-h, --help help for update
-n, --namespace string Specify the namespace to operate in.
--ref string Addressable target reference for Domain Mapping. You can specify a Knative Service name.
--ref string Addressable target reference for Domain Mapping. You can specify a Knative service, a Knative soute or a Kubernetes service.Examples: '--ref ksvc:hello' or simply '--ref hello' for a Knative service 'hello', '--ref kroute:hello' for a Knative route 'hello', '--ref svc:hello' for a Kubernetes service 'hello'. If a prefix is not provided, it is considered as a Knative service.
```

### Options inherited from parent commands
Expand Down
3 changes: 3 additions & 0 deletions pkg/dynamic/fake/fake.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package fake

import (
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
dynamicfake "k8s.io/client-go/dynamic/fake"
Expand All @@ -28,7 +29,9 @@ import (
// CreateFakeKnDynamicClient gives you a dynamic client for testing containing the given objects.
func CreateFakeKnDynamicClient(testNamespace string, objects ...runtime.Object) dynamic.KnDynamicClient {
scheme := runtime.NewScheme()
scheme.AddKnownTypeWithName(schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Service"}, &v1.Service{})
scheme.AddKnownTypeWithName(schema.GroupVersionKind{Group: "serving.knative.dev", Version: "v1", Kind: "Service"}, &servingv1.Service{})
scheme.AddKnownTypeWithName(schema.GroupVersionKind{Group: "serving.knative.dev", Version: "v1", Kind: "Route"}, &servingv1.Route{})
scheme.AddKnownTypeWithName(schema.GroupVersionKind{Group: "eventing.knative.dev", Version: "v1beta1", Kind: "Broker"}, &eventingv1beta1.Broker{})
scheme.AddKnownTypeWithName(schema.GroupVersionKind{Group: "eventing.knative.dev", Version: "v1beta1", Kind: "Subscription"}, &messagingv1beta1.Subscription{})
scheme.AddKnownTypeWithName(schema.GroupVersionKind{Group: "messaging.knative.dev", Version: "v1beta1", Kind: "Channel"}, &messagingv1beta1.Channel{})
Expand Down
10 changes: 4 additions & 6 deletions pkg/kn/commands/domain/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,12 @@ import (

knerrors "knative.dev/client/pkg/errors"
"knative.dev/client/pkg/kn/commands"
"knative.dev/client/pkg/kn/commands/flags"
clientv1alpha1 "knative.dev/client/pkg/serving/v1alpha1"
)

// NewDomainMappingCreateCommand to create event channels
func NewDomainMappingCreateCommand(p *commands.KnParams) *cobra.Command {
var refFlags flags.SinkFlags
var refFlags RefFlags
cmd := &cobra.Command{
Use: "create NAME",
Short: "Create a domain mapping",
Expand All @@ -49,14 +48,14 @@ func NewDomainMappingCreateCommand(p *commands.KnParams) *cobra.Command {
if err != nil {
return err
}
destination, err := refFlags.ResolveSink(dynamicClient, namespace)
reference, err := refFlags.Resolve(dynamicClient, namespace)
if err != nil {
return err
}

builder := clientv1alpha1.NewDomainMappingBuilder(name).
Namespace(namespace).
Reference(*destination.Ref)
Reference(*reference)

client, err := p.NewServingV1alpha1Client(namespace)
if err != nil {
Expand All @@ -72,8 +71,7 @@ func NewDomainMappingCreateCommand(p *commands.KnParams) *cobra.Command {
},
}
commands.AddNamespaceFlags(cmd.Flags(), false)
refFlags.AddWithFlagName(cmd, "ref", "")
cmd.Flag("ref").Usage = "Addressable target reference for Domain Mapping. You can specify a Knative Service name."
refFlags.Add(cmd)
cmd.MarkFlagRequired("ref")
return cmd
}
75 changes: 74 additions & 1 deletion pkg/kn/commands/domain/domain.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,16 @@
package domain

import (
"github.com/spf13/cobra"
"context"
"fmt"
"strings"

"github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
clientdynamic "knative.dev/client/pkg/dynamic"
"knative.dev/client/pkg/kn/commands"
duckv1 "knative.dev/pkg/apis/duck/v1"
)

// NewDomainCommand to manage domain mappings
Expand All @@ -34,3 +41,69 @@ func NewDomainCommand(p *commands.KnParams) *cobra.Command {
domainCmd.AddCommand(NewDomainMappingListCommand(p))
return domainCmd
}

type RefFlags struct {
reference string
}

var refMappings = map[string]schema.GroupVersionResource{
"ksvc": {
Resource: "services",
Group: "serving.knative.dev",
Version: "v1",
},
"kroute": {
Resource: "routes",
Group: "serving.knative.dev",
Version: "v1",
},
"svc": {
Resource: "services",
Group: "",
Version: "v1",
},
}

func (f *RefFlags) Add(cmd *cobra.Command) {
cmd.Flags().StringVar(&f.reference, "ref", "", "")
cmd.Flag("ref").Usage = "Addressable target reference for Domain Mapping. " +
"You can specify a Knative service, a Knative soute or a Kubernetes service." +
"Examples: '--ref ksvc:hello' or simply '--ref hello' for a Knative service 'hello', " +
"'--ref kroute:hello' for a Knative route 'hello', " +
"'--ref svc:hello' for a Kubernetes service 'hello'. " +
"If a prefix is not provided, it is considered as a Knative service."
}

func (f RefFlags) Resolve(knclient clientdynamic.KnDynamicClient, namespace string) (*duckv1.KReference, error) {
client := knclient.RawClient()
if f.reference == "" {
return nil, nil
}

prefix, name := parseType(f.reference)
gvr, ok := refMappings[prefix]
if !ok {
return nil, fmt.Errorf("unsupported sink prefix: '%s'", prefix)
}
obj, err := client.Resource(gvr).Namespace(namespace).Get(context.TODO(), name, metav1.GetOptions{})
if err != nil {
return nil, err
}

result := &duckv1.KReference{
Kind: obj.GetKind(),
APIVersion: obj.GetAPIVersion(),
Name: obj.GetName(),
Namespace: namespace,
}
return result, nil
}

func parseType(ref string) (string, string) {
parts := strings.SplitN(ref, ":", 2)
if len(parts) == 1 {
return "ksvc", parts[0]
} else {
return parts[0], parts[1]
}
}
72 changes: 68 additions & 4 deletions pkg/kn/commands/domain/domain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import (
"bytes"
"testing"

v1 "k8s.io/api/core/v1"

"gotest.tools/v3/assert"

"github.com/spf13/cobra"
Expand All @@ -26,10 +28,11 @@ import (
"k8s.io/client-go/tools/clientcmd"

kndynamic "knative.dev/client/pkg/dynamic"
dynamicfake "knative.dev/client/pkg/dynamic/fake"
"knative.dev/client/pkg/kn/commands"
knflags "knative.dev/client/pkg/kn/flags"
clientservingv1alpha1 "knative.dev/client/pkg/serving/v1alpha1"
v1 "knative.dev/pkg/apis/duck/v1"
duckv1 "knative.dev/pkg/apis/duck/v1"
servingv1 "knative.dev/serving/pkg/apis/serving/v1"
servingv1alpha1 "knative.dev/serving/pkg/apis/serving/v1alpha1"
)
Expand Down Expand Up @@ -73,6 +76,67 @@ func TestDomainCommand(t *testing.T) {
assert.DeepEqual(t, subCommands, expectedSubCommands)
}

type resolveCase struct {
ref string
destination *duckv1.KReference
errContents string
}

func TestResolve(t *testing.T) {
mysvc := &servingv1.Service{
TypeMeta: metav1.TypeMeta{Kind: "Service", APIVersion: "serving.knative.dev/v1"},
ObjectMeta: metav1.ObjectMeta{Name: "mysvc", Namespace: "default"},
}
myroute := &servingv1.Route{
TypeMeta: metav1.TypeMeta{Kind: "Route", APIVersion: "serving.knative.dev/v1"},
ObjectMeta: metav1.ObjectMeta{Name: "myroute", Namespace: "default"},
}
mykubesvc := &v1.Service{
TypeMeta: metav1.TypeMeta{Kind: "Service", APIVersion: "v1"},
ObjectMeta: metav1.ObjectMeta{Name: "mykubesvc", Namespace: "default"},
}

cases := []resolveCase{
{"mysvc", &duckv1.KReference{Kind: "Service",
APIVersion: "serving.knative.dev/v1",
Namespace: "default",
Name: "mysvc"}, ""},
{"ksvc:mysvc", &duckv1.KReference{Kind: "Service",
APIVersion: "serving.knative.dev/v1",
Namespace: "default",
Name: "mysvc"}, ""},
{"kroute:myroute", &duckv1.KReference{Kind: "Route",
APIVersion: "serving.knative.dev/v1",
Namespace: "default",
Name: "myroute"}, ""},
{"svc:mykubesvc", &duckv1.KReference{Kind: "Service",
APIVersion: "v1",
Namespace: "default",
Name: "mykubesvc"}, ""},

{"k8ssvc:foo", nil, "unsupported sink prefix: 'k8ssvc'"},
{"service:foo", nil, "unsupported sink prefix: 'service'"},
}
dynamicClient := dynamicfake.CreateFakeKnDynamicClient("default", mysvc, myroute, mykubesvc)
for _, c := range cases {
i := &RefFlags{c.ref}
result, err := i.Resolve(dynamicClient, "default")
if c.destination != nil {
assert.DeepEqual(t, result, c.destination)
assert.NilError(t, err)
} else {
assert.ErrorContains(t, err, c.errContents)
}
}
}

func TestRefFlagAdd(t *testing.T) {
c := &cobra.Command{Use: "reftest"}
refFlag := new(RefFlags)
refFlag.Add(c)
assert.Equal(t, "ref", c.Flag("ref").Name)
}

func executeDomainCommand(client clientservingv1alpha1.KnServingClient, dynamicClient kndynamic.KnDynamicClient, args ...string) (string, error) {
knParams := &commands.KnParams{}
knParams.ClientConfig = blankConfig
Expand Down Expand Up @@ -103,12 +167,12 @@ func createService(name string) *servingv1.Service {
}
}

func createDomainMapping(name string, ref v1.KReference) *servingv1alpha1.DomainMapping {
func createDomainMapping(name string, ref duckv1.KReference) *servingv1alpha1.DomainMapping {
return clientservingv1alpha1.NewDomainMappingBuilder(name).Namespace("default").Reference(ref).Build()
}

func createServiceRef(service, namespace string) v1.KReference {
return v1.KReference{Name: service,
func createServiceRef(service, namespace string) duckv1.KReference {
return duckv1.KReference{Name: service,
Kind: "Service",
APIVersion: "serving.knative.dev/v1",
Namespace: namespace,
Expand Down
14 changes: 6 additions & 8 deletions pkg/kn/commands/domain/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,17 @@ import (

knerrors "knative.dev/client/pkg/errors"
"knative.dev/client/pkg/kn/commands"
"knative.dev/client/pkg/kn/commands/flags"
)

// NewDomainMappingUpdateCommand to create event channels
func NewDomainMappingUpdateCommand(p *commands.KnParams) *cobra.Command {
var refFlags flags.SinkFlags
var refFlags RefFlags
cmd := &cobra.Command{
Use: "update NAME",
Short: "Update a domain mapping",
Example: `
# Update a domain mappings 'hello.example.com' for Knative service 'hello'
kn domain create hello.example.com --ref hello`,
kn domain create hello.example.com --refFlags hello`,
RunE: func(cmd *cobra.Command, args []string) (err error) {
if len(args) != 1 {
return errors.New("'kn domain create' requires the domain name given as single argument")
Expand Down Expand Up @@ -63,11 +62,11 @@ func NewDomainMappingUpdateCommand(p *commands.KnParams) *cobra.Command {
return err
}

destination, err := refFlags.ResolveSink(dynamicClient, namespace)
reference, err := refFlags.Resolve(dynamicClient, namespace)
if err != nil {
return err
}
toUpdate.Spec.Ref = *destination.Ref
toUpdate.Spec.Ref = *reference

err = client.UpdateDomainMapping(toUpdate)
if err != nil {
Expand All @@ -79,8 +78,7 @@ func NewDomainMappingUpdateCommand(p *commands.KnParams) *cobra.Command {
},
}
commands.AddNamespaceFlags(cmd.Flags(), false)
refFlags.AddWithFlagName(cmd, "ref", "")
cmd.Flag("ref").Usage = "Addressable target reference for Domain Mapping. You can specify a Knative Service name."
cmd.MarkFlagRequired("ref")
refFlags.Add(cmd)
cmd.MarkFlagRequired("refFlags")
return cmd
}

0 comments on commit df9c889

Please sign in to comment.