From d7038f50b66aab67ce3c7bb0b4815bb99c060633 Mon Sep 17 00:00:00 2001 From: Michail Kargakis Date: Fri, 22 Apr 2016 17:36:25 +0200 Subject: [PATCH] unversioned: conversion from new to original label selector --- pkg/api/conversion.go | 28 ++++++++++++ pkg/api/unversioned/helpers.go | 29 ++++++++++++ pkg/api/unversioned/helpers_test.go | 71 +++++++++++++++++++++++++++++ 3 files changed, 128 insertions(+) diff --git a/pkg/api/conversion.go b/pkg/api/conversion.go index 399a4257a84..033e755f4cd 100644 --- a/pkg/api/conversion.go +++ b/pkg/api/conversion.go @@ -17,12 +17,16 @@ limitations under the License. package api import ( + "fmt" + "k8s.io/kubernetes/pkg/api/resource" "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/conversion" "k8s.io/kubernetes/pkg/fields" "k8s.io/kubernetes/pkg/labels" "k8s.io/kubernetes/pkg/util/intstr" + utillabels "k8s.io/kubernetes/pkg/util/labels" + "k8s.io/kubernetes/pkg/util/validation/field" ) func init() { @@ -69,6 +73,9 @@ func init() { Convert_Pointer_float64_To_float64, Convert_float64_To_Pointer_float64, + + Convert_map_to_unversioned_LabelSelector, + Convert_unversioned_LabelSelector_to_map, ) } @@ -195,6 +202,7 @@ func Convert_string_To_labels_Selector(in *string, out *labels.Selector, s conve *out = selector return nil } + func Convert_string_To_fields_Selector(in *string, out *fields.Selector, s conversion.Scope) error { selector, err := fields.ParseSelector(*in) if err != nil { @@ -203,6 +211,7 @@ func Convert_string_To_fields_Selector(in *string, out *fields.Selector, s conve *out = selector return nil } + func Convert_labels_Selector_To_string(in *labels.Selector, out *string, s conversion.Scope) error { if *in == nil { return nil @@ -210,6 +219,7 @@ func Convert_labels_Selector_To_string(in *labels.Selector, out *string, s conve *out = (*in).String() return nil } + func Convert_fields_Selector_To_string(in *fields.Selector, out *string, s conversion.Scope) error { if *in == nil { return nil @@ -217,7 +227,25 @@ func Convert_fields_Selector_To_string(in *fields.Selector, out *string, s conve *out = (*in).String() return nil } + func Convert_resource_Quantity_To_resource_Quantity(in *resource.Quantity, out *resource.Quantity, s conversion.Scope) error { *out = *in return nil } + +func Convert_map_to_unversioned_LabelSelector(in *map[string]string, out *unversioned.LabelSelector, s conversion.Scope) error { + out = new(unversioned.LabelSelector) + for labelKey, labelValue := range *in { + utillabels.AddLabelToSelector(out, labelKey, labelValue) + } + return nil +} + +func Convert_unversioned_LabelSelector_to_map(in *unversioned.LabelSelector, out *map[string]string, s conversion.Scope) error { + var err error + *out, err = unversioned.LabelSelectorAsMap(in) + if err != nil { + err = field.Invalid(field.NewPath("labelSelector"), *in, fmt.Sprintf("cannot convert to old selector: %v", err)) + } + return err +} diff --git a/pkg/api/unversioned/helpers.go b/pkg/api/unversioned/helpers.go index fbbff001975..cb2f2c5cfd0 100644 --- a/pkg/api/unversioned/helpers.go +++ b/pkg/api/unversioned/helpers.go @@ -64,6 +64,35 @@ func LabelSelectorAsSelector(ps *LabelSelector) (labels.Selector, error) { return selector, nil } +// LabelSelectorAsMap converts the LabelSelector api type into a map of strings, ie. the +// original structure of a label selector. Operators that cannot be converted into plain +// labels (Exists, DoesNotExist, NotIn, and In with more than one value) will result in +// an error. +func LabelSelectorAsMap(ps *LabelSelector) (map[string]string, error) { + if ps == nil { + return nil, nil + } + selector := map[string]string{} + for k, v := range ps.MatchLabels { + selector[k] = v + } + for _, expr := range ps.MatchExpressions { + switch expr.Operator { + case LabelSelectorOpIn: + if len(expr.Values) != 1 { + return selector, fmt.Errorf("operator %q without a single value cannot be converted into the old label selector format", expr.Operator) + } + // Should we do anything in case this will override a previous key-value pair? + selector[expr.Key] = expr.Values[0] + case LabelSelectorOpNotIn, LabelSelectorOpExists, LabelSelectorOpDoesNotExist: + return selector, fmt.Errorf("operator %q cannot be converted into the old label selector format", expr.Operator) + default: + return selector, fmt.Errorf("%q is not a valid selector operator", expr.Operator) + } + } + return selector, nil +} + // ParseToLabelSelector parses a string representing a selector into a LabelSelector object. // Note: This function should be kept in sync with the parser in pkg/labels/selector.go func ParseToLabelSelector(selector string) (*LabelSelector, error) { diff --git a/pkg/api/unversioned/helpers_test.go b/pkg/api/unversioned/helpers_test.go index 41b8c15831a..8b0bca620fa 100644 --- a/pkg/api/unversioned/helpers_test.go +++ b/pkg/api/unversioned/helpers_test.go @@ -18,6 +18,7 @@ package unversioned import ( "reflect" + "strings" "testing" "k8s.io/kubernetes/pkg/labels" @@ -81,3 +82,73 @@ func TestLabelSelectorAsSelector(t *testing.T) { } } } + +func TestLabelSelectorAsMap(t *testing.T) { + matchLabels := map[string]string{"foo": "bar"} + matchExpressions := func(operator LabelSelectorOperator, values []string) []LabelSelectorRequirement { + return []LabelSelectorRequirement{{ + Key: "baz", + Operator: operator, + Values: values, + }} + } + + tests := []struct { + in *LabelSelector + out map[string]string + errString string + }{ + {in: nil, out: nil}, + { + in: &LabelSelector{MatchLabels: matchLabels}, + out: map[string]string{"foo": "bar"}, + }, + { + in: &LabelSelector{MatchLabels: matchLabels, MatchExpressions: matchExpressions(LabelSelectorOpIn, []string{"norf"})}, + out: map[string]string{"foo": "bar", "baz": "norf"}, + }, + { + in: &LabelSelector{MatchExpressions: matchExpressions(LabelSelectorOpIn, []string{"norf"})}, + out: map[string]string{"baz": "norf"}, + }, + { + in: &LabelSelector{MatchLabels: matchLabels, MatchExpressions: matchExpressions(LabelSelectorOpIn, []string{"norf", "qux"})}, + out: map[string]string{"foo": "bar"}, + errString: "without a single value cannot be converted", + }, + { + in: &LabelSelector{MatchExpressions: matchExpressions(LabelSelectorOpNotIn, []string{"norf", "qux"})}, + out: map[string]string{}, + errString: "cannot be converted", + }, + { + in: &LabelSelector{MatchLabels: matchLabels, MatchExpressions: matchExpressions(LabelSelectorOpExists, []string{})}, + out: map[string]string{"foo": "bar"}, + errString: "cannot be converted", + }, + { + in: &LabelSelector{MatchExpressions: matchExpressions(LabelSelectorOpDoesNotExist, []string{})}, + out: map[string]string{}, + errString: "cannot be converted", + }, + } + + for i, tc := range tests { + out, err := LabelSelectorAsMap(tc.in) + if err == nil && len(tc.errString) > 0 { + t.Errorf("[%v]expected error but got none.", i) + continue + } + if err != nil && len(tc.errString) == 0 { + t.Errorf("[%v]did not expect error but got: %v", i, err) + continue + } + if err != nil && len(tc.errString) > 0 && !strings.Contains(err.Error(), tc.errString) { + t.Errorf("[%v]expected error with %q but got: %v", i, tc.errString, err) + continue + } + if !reflect.DeepEqual(out, tc.out) { + t.Errorf("[%v]expected:\n\t%+v\nbut got:\n\t%+v", i, tc.out, out) + } + } +}