@@ -16,19 +16,19 @@ package flags
16
16
17
17
import (
18
18
"context"
19
- "fmt"
20
- "strings"
21
19
22
20
"github.com/spf13/cobra"
23
- metav1 "k8s.io/apimachinery/pkg/apis/meta/v1 "
21
+ "github.com/spf13/pflag "
24
22
"k8s.io/apimachinery/pkg/runtime/schema"
25
23
"knative.dev/client/pkg/config"
26
- "knative.dev/pkg/apis"
27
- duckv1 "knative.dev/pkg/apis/duck/v1"
28
-
29
24
clientdynamic "knative.dev/client/pkg/dynamic"
25
+ "knative.dev/client/pkg/flags/sink"
26
+ "knative.dev/client/pkg/util/errors"
27
+ duckv1 "knative.dev/pkg/apis/duck/v1"
30
28
)
31
29
30
+ // SinkFlags holds information about given sink together with optional mappings
31
+ // to allow ease of referencing the common types.
32
32
type SinkFlags struct {
33
33
Sink string
34
34
SinkMappings map [string ]schema.GroupVersionResource
@@ -42,156 +42,81 @@ func NewSinkFlag(mapping map[string]schema.GroupVersionResource) *SinkFlags {
42
42
}
43
43
44
44
// AddWithFlagName configures Sink flag with given flag name and a short flag name
45
- // pass empty short flag name if you don't want to set one
45
+ // pass empty short flag name if you don't want to set one.
46
46
func (i * SinkFlags ) AddWithFlagName (cmd * cobra.Command , fname , short string ) {
47
- flag := "--" + fname
47
+ i .AddToFlagSet (cmd .Flags (), fname , short )
48
+ }
49
+
50
+ // AddToFlagSet configures Sink flag with given flag name and a short flag name
51
+ // pass empty short flag name if you don't want to set one
52
+ func (i * SinkFlags ) AddToFlagSet (fs * pflag.FlagSet , fname , short string ) {
48
53
if short == "" {
49
- cmd . Flags () .StringVar (& i .Sink , fname , "" , "" )
54
+ fs .StringVar (& i .Sink , fname , "" , "" )
50
55
} else {
51
- cmd . Flags () .StringVarP (& i .Sink , fname , short , "" , "" )
56
+ fs .StringVarP (& i .Sink , fname , short , "" , "" )
52
57
}
53
- cmd .Flag (fname ).Usage = "Addressable sink for events. " +
54
- "You can specify a broker, channel, Knative service or URI. " +
55
- "Examples: '" + flag + " broker:nest' for a broker 'nest', " +
56
- "'" + flag + " channel:pipe' for a channel 'pipe', " +
57
- "'" + flag + " ksvc:mysvc:mynamespace' for a Knative service 'mysvc' in another namespace 'mynamespace', " +
58
- "'" + flag + " https://event.receiver.uri' for an HTTP URI, " +
59
- "'" + flag + " ksvc:receiver' or simply '" + flag + " receiver' for a Knative service 'receiver' in the current namespace. " +
60
- "'" + flag + " special.eventing.dev/v1alpha1/channels:pipe' for GroupVersionResource of v1alpha1 'pipe'. " +
61
- "If a prefix is not provided, it is considered as a Knative service in the current namespace."
62
- // Use default mapping if empty
63
- if i .SinkMappings == nil {
64
- i .SinkMappings = defaultSinkMappings
58
+ fs .Lookup (fname ).Usage = sink .Usage (fname )
59
+ }
60
+
61
+ // Add configures Sink flag with name 'Sink' amd short name 's'
62
+ func (i * SinkFlags ) Add (cmd * cobra.Command ) {
63
+ i .AddWithFlagName (cmd , sink .DefaultFlagName , sink .DefaultFlagShorthand )
64
+ }
65
+
66
+ // WithDefaultMappings will return a copy of SinkFlags with provided mappings
67
+ // and the default ones.
68
+ func (i * SinkFlags ) WithDefaultMappings () * SinkFlags {
69
+ sf := & SinkFlags {
70
+ Sink : i .Sink ,
71
+ SinkMappings : make (map [string ]schema.GroupVersionResource ,
72
+ len (i .SinkMappings )+ len (sink .DefaultMappings )),
73
+ }
74
+ for k , v := range sink .DefaultMappings {
75
+ sf .SinkMappings [k ] = v
76
+ }
77
+ for k , v := range i .SinkMappings {
78
+ sf .SinkMappings [k ] = v
65
79
}
66
80
for _ , p := range config .GlobalConfig .SinkMappings () {
67
- //user configuration might override the default configuration
68
- i .SinkMappings [p .Prefix ] = schema.GroupVersionResource {
81
+ // user configuration might override the default configuration
82
+ sf .SinkMappings [p .Prefix ] = schema.GroupVersionResource {
69
83
Resource : p .Resource ,
70
84
Group : p .Group ,
71
85
Version : p .Version ,
72
86
}
73
87
}
88
+ return sf
74
89
}
75
90
76
- // Add configures Sink flag with name 'Sink' amd short name 's'
77
- func (i * SinkFlags ) Add (cmd * cobra.Command ) {
78
- i .AddWithFlagName (cmd , "sink" , "s" )
79
- }
80
-
81
- // SinkPrefixes maps prefixes used for sinks to their GroupVersionResources.
82
- var defaultSinkMappings = map [string ]schema.GroupVersionResource {
83
- "broker" : {
84
- Resource : "brokers" ,
85
- Group : "eventing.knative.dev" ,
86
- Version : "v1" ,
87
- },
88
- // Shorthand alias for service
89
- "ksvc" : {
90
- Resource : "services" ,
91
- Group : "serving.knative.dev" ,
92
- Version : "v1" ,
93
- },
94
- "channel" : {
95
- Resource : "channels" ,
96
- Group : "messaging.knative.dev" ,
97
- Version : "v1" ,
98
- },
91
+ // Parse returns the sink reference, which may refer to URL or to Kubernetes
92
+ // resource. The namespace given should be the current namespace withing the
93
+ // context.
94
+ func (i * SinkFlags ) Parse (namespace string ) (* sink.Reference , error ) {
95
+ // Use default mapping if empty
96
+ sf := i .WithDefaultMappings ()
97
+ return sink .Parse (sf .Sink , namespace , sf .SinkMappings )
99
98
}
100
99
101
100
// ResolveSink returns the Destination referred to by the flags in the acceptor.
102
101
// It validates that any object the user is referring to exists.
103
102
func (i * SinkFlags ) ResolveSink (ctx context.Context , knclient clientdynamic.KnDynamicClient , namespace string ) (* duckv1.Destination , error ) {
104
- client := knclient .RawClient ()
105
- if i .Sink == "" {
106
- return nil , nil
107
- }
108
- // Use default mapping if empty
109
- if i .SinkMappings == nil {
110
- i .SinkMappings = defaultSinkMappings
111
- }
112
- prefix , name , ns := parseSink (i .Sink )
113
- if prefix == "" {
114
- // URI target
115
- uri , err := apis .ParseURL (name )
116
- if err != nil {
117
- return nil , err
118
- }
119
- return & duckv1.Destination {URI : uri }, nil
120
- }
121
- gvr , ok := i .SinkMappings [prefix ]
122
- if ! ok {
123
- if prefix == "svc" || prefix == "service" {
124
- return nil , fmt .Errorf ("unsupported Sink prefix: '%s', please use prefix 'ksvc' for knative service" , prefix )
125
- }
126
- idx := strings .LastIndex (prefix , "/" )
127
- var groupVersion string
128
- var kind string
129
- if idx != - 1 && idx < len (prefix )- 1 {
130
- groupVersion , kind = prefix [:idx ], prefix [idx + 1 :]
131
- } else {
132
- kind = prefix
133
- }
134
- parsedVersion , err := schema .ParseGroupVersion (groupVersion )
135
- if err != nil {
136
- return nil , err
137
- }
138
-
139
- // For the RAWclient the resource name must be in lower case plural form.
140
- // This is the best effort to sanitize the inputs, but the safest way is to provide
141
- // the appropriate form in user's input.
142
- if ! strings .HasSuffix (kind , "s" ) {
143
- kind = kind + "s"
144
- }
145
- kind = strings .ToLower (kind )
146
- gvr = parsedVersion .WithResource (kind )
147
- }
148
- if ns != "" {
149
- namespace = ns
150
- }
151
- obj , err := client .Resource (gvr ).Namespace (namespace ).Get (ctx , name , metav1.GetOptions {})
103
+ s , err := i .Parse (namespace )
152
104
if err != nil {
153
105
return nil , err
154
106
}
155
-
156
- destination := & duckv1.Destination {
157
- Ref : & duckv1.KReference {
158
- Kind : obj .GetKind (),
159
- APIVersion : obj .GetAPIVersion (),
160
- Name : obj .GetName (),
161
- Namespace : namespace ,
162
- },
163
- }
164
- return destination , nil
165
- }
166
-
167
- // parseSink takes the string given by the user into the prefix, name and namespace of
168
- // the object. If the user put a URI instead, the prefix is empty and the name
169
- // is the whole URI.
170
- func parseSink (sink string ) (string , string , string ) {
171
- parts := strings .SplitN (sink , ":" , 3 )
172
- switch {
173
- case len (parts ) == 1 :
174
- return "ksvc" , parts [0 ], ""
175
- case parts [0 ] == "http" || parts [0 ] == "https" :
176
- return "" , sink , ""
177
- case len (parts ) == 3 :
178
- return parts [0 ], parts [1 ], parts [2 ]
179
- default :
180
- return parts [0 ], parts [1 ], ""
107
+ var dest * duckv1.Destination
108
+ dest , err = s .Resolve (ctx , knclient )
109
+ if err != nil {
110
+ // Returning original error that caused sink.ErrSinkIsInvalid as it is
111
+ // directly presented to the end-user.
112
+ return nil , errors .CauseOf (err , sink .ErrSinkIsInvalid )
181
113
}
114
+ return dest , nil
182
115
}
183
116
184
117
// SinkToString prepares a Sink for list output
185
- func SinkToString (sink duckv1.Destination ) string {
186
- if sink .Ref != nil {
187
- if sink .Ref .Kind == "Service" && strings .HasPrefix (sink .Ref .APIVersion , defaultSinkMappings ["ksvc" ].Group ) {
188
- return fmt .Sprintf ("ksvc:%s" , sink .Ref .Name )
189
- } else {
190
- return fmt .Sprintf ("%s:%s" , strings .ToLower (sink .Ref .Kind ), sink .Ref .Name )
191
- }
192
- }
193
- if sink .URI != nil {
194
- return sink .URI .String ()
195
- }
196
- return ""
118
+ // Deprecated: use (*sink.Reference).AsText instead.
119
+ func SinkToString (dest duckv1.Destination ) string {
120
+ ref := sink .GuessFromDestination (dest )
121
+ return ref .String ()
197
122
}
0 commit comments