Skip to content

Commit 7e80dba

Browse files
Merge pull request #2189 from tchap/expose-service-use-labels
OCPBUGS-74543: expose: Fix labels not being added to route
2 parents 7c0e68f + 08d5f27 commit 7e80dba

2 files changed

Lines changed: 133 additions & 3 deletions

File tree

pkg/cli/expose/expose.go

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
1515
"k8s.io/kubectl/pkg/cmd/expose"
1616
kcmdutil "k8s.io/kubectl/pkg/cmd/util"
17+
"k8s.io/kubectl/pkg/generate"
1718
"k8s.io/kubectl/pkg/util"
1819
"k8s.io/kubectl/pkg/util/completion"
1920
"k8s.io/kubectl/pkg/util/templates"
@@ -183,16 +184,19 @@ func (o *ExposeOptions) Run() error {
183184
if len(o.ExposeServiceOptions.Type) != 0 {
184185
return fmt.Errorf("cannot use --type when exposing route")
185186
}
187+
186188
// The upstream generator will incorrectly chose service.Port instead of service.TargetPort
187189
// for the route TargetPort when no port is present. Passing forcePort=true
188190
// causes UnsecuredRoute to always set a Port so the upstream default is not used.
189191
route, err := route.UnsecuredRoute(o.CoreClient, o.Namespace, o.ExposeServiceOptions.Name, info.Name, o.Port, true, o.EnforceNamespace)
190192
if err != nil {
191193
return err
192194
}
193-
route.Spec.Host = o.Hostname
194-
route.Spec.Path = o.Path
195-
route.Spec.WildcardPolicy = routev1.WildcardPolicyType(o.WildcardPolicy)
195+
196+
if err := o.finalizeRoute(route); err != nil {
197+
return err
198+
}
199+
196200
if err := util.CreateOrUpdateAnnotation(kcmdutil.GetFlagBool(o.Cmd, kcmdutil.ApplyAnnotationsFlag), route, exposeCmdJSONEncoder()); err != nil {
197201
return err
198202
}
@@ -214,3 +218,27 @@ func (o *ExposeOptions) Run() error {
214218

215219
return o.ExposeServiceOptions.RunExpose(o.Cmd, o.Args)
216220
}
221+
222+
func (o *ExposeOptions) finalizeRoute(route *routev1.Route) error {
223+
var labels map[string]string
224+
if o.ExposeServiceOptions != nil && len(o.ExposeServiceOptions.Labels) > 0 {
225+
var err error
226+
labels, err = generate.ParseLabels(o.ExposeServiceOptions.Labels)
227+
if err != nil {
228+
return fmt.Errorf("unable to parse labels: %w", err)
229+
}
230+
}
231+
232+
if len(route.ObjectMeta.Labels) == 0 {
233+
route.ObjectMeta.Labels = labels
234+
} else {
235+
for k, v := range labels {
236+
route.ObjectMeta.Labels[k] = v
237+
}
238+
}
239+
240+
route.Spec.Host = o.Hostname
241+
route.Spec.Path = o.Path
242+
route.Spec.WildcardPolicy = routev1.WildcardPolicyType(o.WildcardPolicy)
243+
return nil
244+
}

pkg/cli/expose/expose_test.go

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
package expose
2+
3+
import (
4+
"testing"
5+
6+
"github.com/google/go-cmp/cmp"
7+
"k8s.io/kubectl/pkg/cmd/expose"
8+
9+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
10+
"k8s.io/apimachinery/pkg/util/intstr"
11+
12+
routev1 "github.com/openshift/api/route/v1"
13+
)
14+
15+
func TestExposeOptions_FinalizeRoute(t *testing.T) {
16+
route := &routev1.Route{
17+
TypeMeta: metav1.TypeMeta{APIVersion: routev1.GroupVersion.String(), Kind: "Route"},
18+
ObjectMeta: metav1.ObjectMeta{
19+
Name: "example-api",
20+
Labels: map[string]string{
21+
"app": "example",
22+
},
23+
},
24+
Spec: routev1.RouteSpec{
25+
To: routev1.RouteTargetReference{
26+
Name: "example-api",
27+
},
28+
Port: &routev1.RoutePort{
29+
TargetPort: intstr.FromInt32(8443),
30+
},
31+
},
32+
}
33+
34+
newExpectedRoute := func(hook func(*routev1.Route)) *routev1.Route {
35+
r := route.DeepCopy()
36+
if hook != nil {
37+
hook(r)
38+
}
39+
return r
40+
}
41+
42+
testCases := []struct {
43+
name string
44+
opts *ExposeOptions
45+
expectedRoute *routev1.Route
46+
expectedErrMsg string
47+
}{
48+
{
49+
name: "happy path",
50+
opts: &ExposeOptions{
51+
Hostname: "example.com",
52+
Path: "/api",
53+
WildcardPolicy: string(routev1.WildcardPolicyNone),
54+
},
55+
expectedRoute: newExpectedRoute(func(r *routev1.Route) {
56+
r.Spec.Host = "example.com"
57+
r.Spec.Path = "/api"
58+
r.Spec.WildcardPolicy = routev1.WildcardPolicyNone
59+
}),
60+
},
61+
{
62+
name: "custom labels added",
63+
opts: &ExposeOptions{
64+
ExposeServiceOptions: &expose.ExposeServiceOptions{
65+
Labels: "label1=value1,label2=value2",
66+
},
67+
},
68+
expectedRoute: newExpectedRoute(func(r *routev1.Route) {
69+
r.ObjectMeta.Labels["label1"] = "value1"
70+
r.ObjectMeta.Labels["label2"] = "value2"
71+
}),
72+
},
73+
{
74+
name: "invalid labels option",
75+
opts: &ExposeOptions{
76+
ExposeServiceOptions: &expose.ExposeServiceOptions{
77+
Labels: "label1,label2",
78+
},
79+
},
80+
expectedRoute: newExpectedRoute(nil),
81+
expectedErrMsg: "unable to parse labels: unexpected label spec: label1",
82+
},
83+
}
84+
85+
for _, tc := range testCases {
86+
t.Run(tc.name, func(t *testing.T) {
87+
got := route.DeepCopy()
88+
err := tc.opts.finalizeRoute(got)
89+
if !cmp.Equal(got, tc.expectedRoute) {
90+
t.Errorf("Unexpected route:\n%s", cmp.Diff(tc.expectedRoute, got))
91+
}
92+
93+
var errMsg string
94+
if err != nil {
95+
errMsg = err.Error()
96+
}
97+
if tc.expectedErrMsg != errMsg {
98+
t.Errorf("Unexpected error: want = %q, got = %q", tc.expectedErrMsg, errMsg)
99+
}
100+
})
101+
}
102+
}

0 commit comments

Comments
 (0)