| ... | ... |
@@ -2,7 +2,6 @@ package config |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 | 4 |
"fmt" |
| 5 |
- "reflect" |
|
| 6 | 5 |
|
| 7 | 6 |
kapi "github.com/GoogleCloudPlatform/kubernetes/pkg/api" |
| 8 | 7 |
errs "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors" |
| ... | ... |
@@ -10,8 +9,10 @@ import ( |
| 10 | 10 |
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl" |
| 11 | 11 |
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels" |
| 12 | 12 |
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" |
| 13 |
+ |
|
| 13 | 14 |
"github.com/openshift/origin/pkg/config/api" |
| 14 | 15 |
deployapi "github.com/openshift/origin/pkg/deploy/api" |
| 16 |
+ "github.com/openshift/origin/pkg/util" |
|
| 15 | 17 |
) |
| 16 | 18 |
|
| 17 | 19 |
// ApplyResult holds the response from the REST server and potential errors |
| ... | ... |
@@ -103,40 +104,40 @@ func addLabelError(kind string, err error) error {
|
| 103 | 103 |
func AddConfigLabel(obj runtime.Object, labels labels.Set) error {
|
| 104 | 104 |
switch t := obj.(type) {
|
| 105 | 105 |
case *kapi.Pod: |
| 106 |
- if err := mergeMaps(&t.Labels, labels, ErrorOnDifferentDstKeyValue); err != nil {
|
|
| 106 |
+ if err := util.MergeInto(&t.Labels, labels, util.ErrorOnDifferentDstKeyValue); err != nil {
|
|
| 107 | 107 |
return addLabelError("Pod", err)
|
| 108 | 108 |
} |
| 109 | 109 |
case *kapi.Service: |
| 110 |
- if err := mergeMaps(&t.Labels, labels, ErrorOnDifferentDstKeyValue); err != nil {
|
|
| 110 |
+ if err := util.MergeInto(&t.Labels, labels, util.ErrorOnDifferentDstKeyValue); err != nil {
|
|
| 111 | 111 |
return addLabelError("Service", err)
|
| 112 | 112 |
} |
| 113 | 113 |
case *kapi.ReplicationController: |
| 114 |
- if err := mergeMaps(&t.Labels, labels, ErrorOnDifferentDstKeyValue); err != nil {
|
|
| 114 |
+ if err := util.MergeInto(&t.Labels, labels, util.ErrorOnDifferentDstKeyValue); err != nil {
|
|
| 115 | 115 |
return addLabelError("ReplicationController", err)
|
| 116 | 116 |
} |
| 117 |
- if err := mergeMaps(&t.DesiredState.PodTemplate.Labels, labels, ErrorOnDifferentDstKeyValue); err != nil {
|
|
| 117 |
+ if err := util.MergeInto(&t.DesiredState.PodTemplate.Labels, labels, util.ErrorOnDifferentDstKeyValue); err != nil {
|
|
| 118 | 118 |
return addLabelError("ReplicationController.PodTemplate", err)
|
| 119 | 119 |
} |
| 120 |
- if err := mergeMaps(&t.DesiredState.PodTemplate.Labels, t.DesiredState.ReplicaSelector, ErrorOnDifferentDstKeyValue); err != nil {
|
|
| 120 |
+ if err := util.MergeInto(&t.DesiredState.PodTemplate.Labels, t.DesiredState.ReplicaSelector, util.ErrorOnDifferentDstKeyValue); err != nil {
|
|
| 121 | 121 |
return addLabelError("ReplicationController.ReplicaSelector", err)
|
| 122 | 122 |
} |
| 123 | 123 |
// The ReplicaSelector and DesiredState.PodTemplate.Labels need to make |
| 124 | 124 |
// create succeed |
| 125 |
- if err := mergeMaps(&t.DesiredState.ReplicaSelector, t.DesiredState.PodTemplate.Labels, ErrorOnDifferentDstKeyValue); err != nil {
|
|
| 125 |
+ if err := util.MergeInto(&t.DesiredState.ReplicaSelector, t.DesiredState.PodTemplate.Labels, util.ErrorOnDifferentDstKeyValue); err != nil {
|
|
| 126 | 126 |
return addLabelError("ReplicationController.PodTemplate", err)
|
| 127 | 127 |
} |
| 128 | 128 |
case *deployapi.Deployment: |
| 129 |
- if err := mergeMaps(&t.Labels, labels, ErrorOnDifferentDstKeyValue); err != nil {
|
|
| 129 |
+ if err := util.MergeInto(&t.Labels, labels, util.ErrorOnDifferentDstKeyValue); err != nil {
|
|
| 130 | 130 |
return addLabelError("Deployment", err)
|
| 131 | 131 |
} |
| 132 |
- if err := mergeMaps(&t.ControllerTemplate.PodTemplate.Labels, labels, ErrorOnDifferentDstKeyValue); err != nil {
|
|
| 132 |
+ if err := util.MergeInto(&t.ControllerTemplate.PodTemplate.Labels, labels, util.ErrorOnDifferentDstKeyValue); err != nil {
|
|
| 133 | 133 |
return addLabelError("Deployment.ControllerTemplate.PodTemplate", err)
|
| 134 | 134 |
} |
| 135 | 135 |
case *deployapi.DeploymentConfig: |
| 136 |
- if err := mergeMaps(&t.Labels, labels, ErrorOnDifferentDstKeyValue); err != nil {
|
|
| 136 |
+ if err := util.MergeInto(&t.Labels, labels, util.ErrorOnDifferentDstKeyValue); err != nil {
|
|
| 137 | 137 |
return addLabelError("DeploymentConfig", err)
|
| 138 | 138 |
} |
| 139 |
- if err := mergeMaps(&t.Template.ControllerTemplate.PodTemplate.Labels, labels, ErrorOnDifferentDstKeyValue); err != nil {
|
|
| 139 |
+ if err := util.MergeInto(&t.Template.ControllerTemplate.PodTemplate.Labels, labels, util.ErrorOnDifferentDstKeyValue); err != nil {
|
|
| 140 | 140 |
return addLabelError("DeploymentConfig.ControllerTemplate.PodTemplate", err)
|
| 141 | 141 |
} |
| 142 | 142 |
default: |
| ... | ... |
@@ -168,72 +169,3 @@ func AddConfigLabels(c *api.Config, labels labels.Set) errs.ValidationErrorList |
| 168 | 168 |
} |
| 169 | 169 |
return itemErrors.Prefix("Config")
|
| 170 | 170 |
} |
| 171 |
- |
|
| 172 |
-// mergeMaps flags |
|
| 173 |
-const ( |
|
| 174 |
- OverwriteExistingDstKey = 1 << iota |
|
| 175 |
- ErrorOnExistingDstKey = 1 << iota |
|
| 176 |
- ErrorOnDifferentDstKeyValue = 1 << iota |
|
| 177 |
-) |
|
| 178 |
- |
|
| 179 |
-// mergeMaps merges items from a src map into a dst map. |
|
| 180 |
-// Returns an error when the maps are not of the same type. |
|
| 181 |
-// Flags: |
|
| 182 |
-// - ErrorOnExistingDstKey |
|
| 183 |
-// When set: Return an error if any of the dst keys is already set. |
|
| 184 |
-// - ErrorOnDifferentDstKeyValue |
|
| 185 |
-// When set: Return an error if any of the dst keys is already set |
|
| 186 |
-// to a different value than src key. |
|
| 187 |
-// - OverwriteDstKey |
|
| 188 |
-// When set: Overwrite existing dst key value with src key value. |
|
| 189 |
-func mergeMaps(dst, src interface{}, flags int) error {
|
|
| 190 |
- dstVal := reflect.ValueOf(dst) |
|
| 191 |
- srcVal := reflect.ValueOf(src) |
|
| 192 |
- |
|
| 193 |
- if dstVal.Kind() == reflect.Interface || dstVal.Kind() == reflect.Ptr {
|
|
| 194 |
- dstVal = dstVal.Elem() |
|
| 195 |
- } |
|
| 196 |
- if srcVal.Kind() == reflect.Interface || srcVal.Kind() == reflect.Ptr {
|
|
| 197 |
- srcVal = srcVal.Elem() |
|
| 198 |
- } |
|
| 199 |
- |
|
| 200 |
- if !dstVal.IsValid() {
|
|
| 201 |
- return fmt.Errorf("Dst is not a valid value")
|
|
| 202 |
- } |
|
| 203 |
- if dstVal.Kind() != reflect.Map {
|
|
| 204 |
- return fmt.Errorf("Dst is not a map")
|
|
| 205 |
- } |
|
| 206 |
- |
|
| 207 |
- dstTyp := dstVal.Type() |
|
| 208 |
- srcTyp := srcVal.Type() |
|
| 209 |
- if !dstTyp.AssignableTo(srcTyp) {
|
|
| 210 |
- return fmt.Errorf("Type mismatch, can't assign '%v' to '%v'", srcTyp, dstTyp)
|
|
| 211 |
- } |
|
| 212 |
- |
|
| 213 |
- if dstVal.IsNil() {
|
|
| 214 |
- if !dstVal.CanSet() {
|
|
| 215 |
- return fmt.Errorf("Dst value is (not addressable) nil, pass a pointer instead")
|
|
| 216 |
- } |
|
| 217 |
- dstVal.Set(reflect.MakeMap(dstTyp)) |
|
| 218 |
- } |
|
| 219 |
- |
|
| 220 |
- for _, k := range srcVal.MapKeys() {
|
|
| 221 |
- if dstVal.MapIndex(k).IsValid() {
|
|
| 222 |
- if flags&ErrorOnExistingDstKey != 0 {
|
|
| 223 |
- return fmt.Errorf("ErrorOnExistingDstKey flag: Dst key already set to a different value, '%v'='%v'", k, dstVal.MapIndex(k))
|
|
| 224 |
- } |
|
| 225 |
- if dstVal.MapIndex(k).String() != srcVal.MapIndex(k).String() {
|
|
| 226 |
- if flags&ErrorOnDifferentDstKeyValue != 0 {
|
|
| 227 |
- return fmt.Errorf("ErrorOnDifferentDstKeyValue flag: Dst key already set to a different value, '%v'='%v'", k, dstVal.MapIndex(k))
|
|
| 228 |
- } |
|
| 229 |
- if flags&OverwriteExistingDstKey != 0 {
|
|
| 230 |
- dstVal.SetMapIndex(k, srcVal.MapIndex(k)) |
|
| 231 |
- } |
|
| 232 |
- } |
|
| 233 |
- } else {
|
|
| 234 |
- dstVal.SetMapIndex(k, srcVal.MapIndex(k)) |
|
| 235 |
- } |
|
| 236 |
- } |
|
| 237 |
- |
|
| 238 |
- return nil |
|
| 239 |
-} |
| ... | ... |
@@ -294,76 +294,3 @@ func TestAddConfigLabels(t *testing.T) {
|
| 294 | 294 |
} |
| 295 | 295 |
} |
| 296 | 296 |
} |
| 297 |
- |
|
| 298 |
-func TestMergeMaps(t *testing.T) {
|
|
| 299 |
- testCases := []struct {
|
|
| 300 |
- dst interface{}
|
|
| 301 |
- src interface{}
|
|
| 302 |
- flags int |
|
| 303 |
- shouldPass bool |
|
| 304 |
- expected interface{}
|
|
| 305 |
- }{
|
|
| 306 |
- { // Test empty maps
|
|
| 307 |
- map[int]int{},
|
|
| 308 |
- map[int]int{},
|
|
| 309 |
- 0, |
|
| 310 |
- true, |
|
| 311 |
- map[int]int{},
|
|
| 312 |
- }, |
|
| 313 |
- { // Test dst + src => expected
|
|
| 314 |
- map[int]string{1: "foo"},
|
|
| 315 |
- map[int]string{2: "bar"},
|
|
| 316 |
- 0, |
|
| 317 |
- true, |
|
| 318 |
- map[int]string{1: "foo", 2: "bar"},
|
|
| 319 |
- }, |
|
| 320 |
- { // Test dst + src => expected, do not overwrite dst
|
|
| 321 |
- map[string]string{"foo": "bar"},
|
|
| 322 |
- map[string]string{"foo": ""},
|
|
| 323 |
- 0, |
|
| 324 |
- true, |
|
| 325 |
- map[string]string{"foo": "bar"},
|
|
| 326 |
- }, |
|
| 327 |
- { // Test dst + src => expected, overwrite dst
|
|
| 328 |
- map[string]string{"foo": "bar"},
|
|
| 329 |
- map[string]string{"foo": ""},
|
|
| 330 |
- OverwriteExistingDstKey, |
|
| 331 |
- true, |
|
| 332 |
- map[string]string{"foo": ""},
|
|
| 333 |
- }, |
|
| 334 |
- { // Test dst + src => expected, error on existing key value
|
|
| 335 |
- map[string]string{"foo": "bar"},
|
|
| 336 |
- map[string]string{"foo": "bar"},
|
|
| 337 |
- ErrorOnExistingDstKey | OverwriteExistingDstKey, |
|
| 338 |
- false, |
|
| 339 |
- map[string]string{"foo": "bar"},
|
|
| 340 |
- }, |
|
| 341 |
- { // Test dst + src => expected, do not error on same key value
|
|
| 342 |
- map[string]string{"foo": "bar"},
|
|
| 343 |
- map[string]string{"foo": "bar"},
|
|
| 344 |
- ErrorOnDifferentDstKeyValue | OverwriteExistingDstKey, |
|
| 345 |
- true, |
|
| 346 |
- map[string]string{"foo": "bar"},
|
|
| 347 |
- }, |
|
| 348 |
- { // Test dst + src => expected, error on different key value
|
|
| 349 |
- map[string]string{"foo": "bar"},
|
|
| 350 |
- map[string]string{"foo": ""},
|
|
| 351 |
- ErrorOnDifferentDstKeyValue | OverwriteExistingDstKey, |
|
| 352 |
- false, |
|
| 353 |
- map[string]string{"foo": "bar"},
|
|
| 354 |
- }, |
|
| 355 |
- } |
|
| 356 |
- |
|
| 357 |
- for i, test := range testCases {
|
|
| 358 |
- err := mergeMaps(test.dst, test.src, test.flags) |
|
| 359 |
- if err != nil && test.shouldPass {
|
|
| 360 |
- t.Errorf("Unexpected error while merging maps on testCase[%v].", i)
|
|
| 361 |
- } |
|
| 362 |
- if err == nil && !test.shouldPass {
|
|
| 363 |
- t.Errorf("Unexpected non-error while merging maps on testCase[%v].", i)
|
|
| 364 |
- } |
|
| 365 |
- if !reflect.DeepEqual(test.dst, test.expected) {
|
|
| 366 |
- t.Errorf("Unexpected map on testCase[%v]. Expected: %v, got: %v.", i, test.expected, test.dst)
|
|
| 367 |
- } |
|
| 368 |
- } |
|
| 369 |
-} |
| 0 | 4 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,75 @@ |
| 0 |
+package util |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "fmt" |
|
| 4 |
+ "reflect" |
|
| 5 |
+) |
|
| 6 |
+ |
|
| 7 |
+// MergeInto flags |
|
| 8 |
+const ( |
|
| 9 |
+ OverwriteExistingDstKey = 1 << iota |
|
| 10 |
+ ErrorOnExistingDstKey = 1 << iota |
|
| 11 |
+ ErrorOnDifferentDstKeyValue = 1 << iota |
|
| 12 |
+) |
|
| 13 |
+ |
|
| 14 |
+// MergeInto merges items from a src map into a dst map. |
|
| 15 |
+// Returns an error when the maps are not of the same type. |
|
| 16 |
+// Flags: |
|
| 17 |
+// - ErrorOnExistingDstKey |
|
| 18 |
+// When set: Return an error if any of the dst keys is already set. |
|
| 19 |
+// - ErrorOnDifferentDstKeyValue |
|
| 20 |
+// When set: Return an error if any of the dst keys is already set |
|
| 21 |
+// to a different value than src key. |
|
| 22 |
+// - OverwriteDstKey |
|
| 23 |
+// When set: Overwrite existing dst key value with src key value. |
|
| 24 |
+func MergeInto(dst, src interface{}, flags int) error {
|
|
| 25 |
+ dstVal := reflect.ValueOf(dst) |
|
| 26 |
+ srcVal := reflect.ValueOf(src) |
|
| 27 |
+ |
|
| 28 |
+ if dstVal.Kind() == reflect.Interface || dstVal.Kind() == reflect.Ptr {
|
|
| 29 |
+ dstVal = dstVal.Elem() |
|
| 30 |
+ } |
|
| 31 |
+ if srcVal.Kind() == reflect.Interface || srcVal.Kind() == reflect.Ptr {
|
|
| 32 |
+ srcVal = srcVal.Elem() |
|
| 33 |
+ } |
|
| 34 |
+ |
|
| 35 |
+ if !dstVal.IsValid() {
|
|
| 36 |
+ return fmt.Errorf("Dst is not a valid value")
|
|
| 37 |
+ } |
|
| 38 |
+ if dstVal.Kind() != reflect.Map {
|
|
| 39 |
+ return fmt.Errorf("Dst is not a map")
|
|
| 40 |
+ } |
|
| 41 |
+ |
|
| 42 |
+ dstTyp := dstVal.Type() |
|
| 43 |
+ srcTyp := srcVal.Type() |
|
| 44 |
+ if !dstTyp.AssignableTo(srcTyp) {
|
|
| 45 |
+ return fmt.Errorf("Type mismatch, can't assign '%v' to '%v'", srcTyp, dstTyp)
|
|
| 46 |
+ } |
|
| 47 |
+ |
|
| 48 |
+ if dstVal.IsNil() {
|
|
| 49 |
+ if !dstVal.CanSet() {
|
|
| 50 |
+ return fmt.Errorf("Dst value is (not addressable) nil, pass a pointer instead")
|
|
| 51 |
+ } |
|
| 52 |
+ dstVal.Set(reflect.MakeMap(dstTyp)) |
|
| 53 |
+ } |
|
| 54 |
+ |
|
| 55 |
+ for _, k := range srcVal.MapKeys() {
|
|
| 56 |
+ if dstVal.MapIndex(k).IsValid() {
|
|
| 57 |
+ if flags&ErrorOnExistingDstKey != 0 {
|
|
| 58 |
+ return fmt.Errorf("ErrorOnExistingDstKey flag: Dst key already set to a different value, '%v'='%v'", k, dstVal.MapIndex(k))
|
|
| 59 |
+ } |
|
| 60 |
+ if dstVal.MapIndex(k).String() != srcVal.MapIndex(k).String() {
|
|
| 61 |
+ if flags&ErrorOnDifferentDstKeyValue != 0 {
|
|
| 62 |
+ return fmt.Errorf("ErrorOnDifferentDstKeyValue flag: Dst key already set to a different value, '%v'='%v'", k, dstVal.MapIndex(k))
|
|
| 63 |
+ } |
|
| 64 |
+ if flags&OverwriteExistingDstKey != 0 {
|
|
| 65 |
+ dstVal.SetMapIndex(k, srcVal.MapIndex(k)) |
|
| 66 |
+ } |
|
| 67 |
+ } |
|
| 68 |
+ } else {
|
|
| 69 |
+ dstVal.SetMapIndex(k, srcVal.MapIndex(k)) |
|
| 70 |
+ } |
|
| 71 |
+ } |
|
| 72 |
+ |
|
| 73 |
+ return nil |
|
| 74 |
+} |
| 0 | 75 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,79 @@ |
| 0 |
+package util |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "reflect" |
|
| 4 |
+ "testing" |
|
| 5 |
+) |
|
| 6 |
+ |
|
| 7 |
+func TestMergeMaps(t *testing.T) {
|
|
| 8 |
+ testCases := []struct {
|
|
| 9 |
+ dst interface{}
|
|
| 10 |
+ src interface{}
|
|
| 11 |
+ flags int |
|
| 12 |
+ shouldPass bool |
|
| 13 |
+ expected interface{}
|
|
| 14 |
+ }{
|
|
| 15 |
+ { // Test empty maps
|
|
| 16 |
+ map[int]int{},
|
|
| 17 |
+ map[int]int{},
|
|
| 18 |
+ 0, |
|
| 19 |
+ true, |
|
| 20 |
+ map[int]int{},
|
|
| 21 |
+ }, |
|
| 22 |
+ { // Test dst + src => expected
|
|
| 23 |
+ map[int]string{1: "foo"},
|
|
| 24 |
+ map[int]string{2: "bar"},
|
|
| 25 |
+ 0, |
|
| 26 |
+ true, |
|
| 27 |
+ map[int]string{1: "foo", 2: "bar"},
|
|
| 28 |
+ }, |
|
| 29 |
+ { // Test dst + src => expected, do not overwrite dst
|
|
| 30 |
+ map[string]string{"foo": "bar"},
|
|
| 31 |
+ map[string]string{"foo": ""},
|
|
| 32 |
+ 0, |
|
| 33 |
+ true, |
|
| 34 |
+ map[string]string{"foo": "bar"},
|
|
| 35 |
+ }, |
|
| 36 |
+ { // Test dst + src => expected, overwrite dst
|
|
| 37 |
+ map[string]string{"foo": "bar"},
|
|
| 38 |
+ map[string]string{"foo": ""},
|
|
| 39 |
+ OverwriteExistingDstKey, |
|
| 40 |
+ true, |
|
| 41 |
+ map[string]string{"foo": ""},
|
|
| 42 |
+ }, |
|
| 43 |
+ { // Test dst + src => expected, error on existing key value
|
|
| 44 |
+ map[string]string{"foo": "bar"},
|
|
| 45 |
+ map[string]string{"foo": "bar"},
|
|
| 46 |
+ ErrorOnExistingDstKey | OverwriteExistingDstKey, |
|
| 47 |
+ false, |
|
| 48 |
+ map[string]string{"foo": "bar"},
|
|
| 49 |
+ }, |
|
| 50 |
+ { // Test dst + src => expected, do not error on same key value
|
|
| 51 |
+ map[string]string{"foo": "bar"},
|
|
| 52 |
+ map[string]string{"foo": "bar"},
|
|
| 53 |
+ ErrorOnDifferentDstKeyValue | OverwriteExistingDstKey, |
|
| 54 |
+ true, |
|
| 55 |
+ map[string]string{"foo": "bar"},
|
|
| 56 |
+ }, |
|
| 57 |
+ { // Test dst + src => expected, error on different key value
|
|
| 58 |
+ map[string]string{"foo": "bar"},
|
|
| 59 |
+ map[string]string{"foo": ""},
|
|
| 60 |
+ ErrorOnDifferentDstKeyValue | OverwriteExistingDstKey, |
|
| 61 |
+ false, |
|
| 62 |
+ map[string]string{"foo": "bar"},
|
|
| 63 |
+ }, |
|
| 64 |
+ } |
|
| 65 |
+ |
|
| 66 |
+ for i, test := range testCases {
|
|
| 67 |
+ err := MergeInto(test.dst, test.src, test.flags) |
|
| 68 |
+ if err != nil && test.shouldPass {
|
|
| 69 |
+ t.Errorf("Unexpected error while merging maps on testCase[%v].", i)
|
|
| 70 |
+ } |
|
| 71 |
+ if err == nil && !test.shouldPass {
|
|
| 72 |
+ t.Errorf("Unexpected non-error while merging maps on testCase[%v].", i)
|
|
| 73 |
+ } |
|
| 74 |
+ if !reflect.DeepEqual(test.dst, test.expected) {
|
|
| 75 |
+ t.Errorf("Unexpected map on testCase[%v]. Expected: %v, got: %v.", i, test.expected, test.dst)
|
|
| 76 |
+ } |
|
| 77 |
+ } |
|
| 78 |
+} |