Browse code

API types for addition of scheduled to image streams

Clayton Coleman authored on 2016/01/27 15:01:45
Showing 12 changed files
... ...
@@ -19859,6 +19859,10 @@
19859 19859
      "insecure": {
19860 19860
       "type": "boolean",
19861 19861
       "description": "if true, the server may bypass certificate verification or connect directly over HTTP during image import"
19862
+     },
19863
+     "scheduled": {
19864
+      "type": "boolean",
19865
+      "description": "if true, the server will periodically check to ensure this tag is up to date"
19862 19866
      }
19863 19867
     }
19864 19868
    },
... ...
@@ -2352,6 +2352,7 @@ func deepCopy_api_TagEventList(in imageapi.TagEventList, out *imageapi.TagEventL
2352 2352
 
2353 2353
 func deepCopy_api_TagImportPolicy(in imageapi.TagImportPolicy, out *imageapi.TagImportPolicy, c *conversion.Cloner) error {
2354 2354
 	out.Insecure = in.Insecure
2355
+	out.Scheduled = in.Scheduled
2355 2356
 	return nil
2356 2357
 }
2357 2358
 
... ...
@@ -4114,6 +4114,7 @@ func autoconvert_api_TagImportPolicy_To_v1_TagImportPolicy(in *imageapi.TagImpor
4114 4114
 		defaulting.(func(*imageapi.TagImportPolicy))(in)
4115 4115
 	}
4116 4116
 	out.Insecure = in.Insecure
4117
+	out.Scheduled = in.Scheduled
4117 4118
 	return nil
4118 4119
 }
4119 4120
 
... ...
@@ -4526,6 +4527,7 @@ func autoconvert_v1_TagImportPolicy_To_api_TagImportPolicy(in *imageapiv1.TagImp
4526 4526
 		defaulting.(func(*imageapiv1.TagImportPolicy))(in)
4527 4527
 	}
4528 4528
 	out.Insecure = in.Insecure
4529
+	out.Scheduled = in.Scheduled
4529 4530
 	return nil
4530 4531
 }
4531 4532
 
... ...
@@ -2275,6 +2275,7 @@ func deepCopy_v1_TagEventCondition(in imageapiv1.TagEventCondition, out *imageap
2275 2275
 
2276 2276
 func deepCopy_v1_TagImportPolicy(in imageapiv1.TagImportPolicy, out *imageapiv1.TagImportPolicy, c *conversion.Cloner) error {
2277 2277
 	out.Insecure = in.Insecure
2278
+	out.Scheduled = in.Scheduled
2278 2279
 	return nil
2279 2280
 }
2280 2281
 
... ...
@@ -2112,6 +2112,7 @@ func deepCopy_v1beta3_TagEventCondition(in imageapiv1beta3.TagEventCondition, ou
2112 2112
 
2113 2113
 func deepCopy_v1beta3_TagImportPolicy(in imageapiv1beta3.TagImportPolicy, out *imageapiv1beta3.TagImportPolicy, c *conversion.Cloner) error {
2114 2114
 	out.Insecure = in.Insecure
2115
+	out.Scheduled = in.Scheduled
2115 2116
 	return nil
2116 2117
 }
2117 2118
 
... ...
@@ -112,6 +112,8 @@ type TagReference struct {
112 112
 type TagImportPolicy struct {
113 113
 	// Insecure is true if the server may bypass certificate verification or connect directly over HTTP during image import.
114 114
 	Insecure bool
115
+	// Scheduled indicates to the server that this tag should be periodically checked to ensure it is up to date, and imported
116
+	Scheduled bool
115 117
 }
116 118
 
117 119
 // ImageStreamStatus contains information about the state of this image stream.
... ...
@@ -195,7 +195,8 @@ func init() {
195 195
 					Annotations: curr.Annotations,
196 196
 					Reference:   curr.Reference,
197 197
 					ImportPolicy: newer.TagImportPolicy{
198
-						Insecure: curr.ImportPolicy.Insecure,
198
+						Insecure:  curr.ImportPolicy.Insecure,
199
+						Scheduled: curr.ImportPolicy.Scheduled,
199 200
 					},
200 201
 				}
201 202
 				if curr.Generation != nil {
... ...
@@ -223,7 +224,8 @@ func init() {
223 223
 					Annotations: newTagReference.Annotations,
224 224
 					Reference:   newTagReference.Reference,
225 225
 					ImportPolicy: TagImportPolicy{
226
-						Insecure: newTagReference.ImportPolicy.Insecure,
226
+						Insecure:  newTagReference.ImportPolicy.Insecure,
227
+						Scheduled: newTagReference.ImportPolicy.Scheduled,
227 228
 					},
228 229
 				}
229 230
 				if newTagReference.Generation != nil {
... ...
@@ -90,6 +90,8 @@ type NamedTagReference struct {
90 90
 type TagImportPolicy struct {
91 91
 	// Insecure is true if the server may bypass certificate verification or connect directly over HTTP during image import.
92 92
 	Insecure bool `json:"insecure,omitempty" description:"if true, the server may bypass certificate verification or connect directly over HTTP during image import"`
93
+	// Scheduled indicates to the server that this tag should be periodically checked to ensure it is up to date, and imported
94
+	Scheduled bool `json:"scheduled,omitempty" description:"if true, the server will periodically check to ensure this tag is up to date"`
93 95
 }
94 96
 
95 97
 // ImageStreamStatus contains information about the state of this image stream.
... ...
@@ -243,7 +243,8 @@ func init() {
243 243
 					Annotations: curr.Annotations,
244 244
 					Reference:   curr.Reference,
245 245
 					ImportPolicy: newer.TagImportPolicy{
246
-						Insecure: curr.ImportPolicy.Insecure,
246
+						Insecure:  curr.ImportPolicy.Insecure,
247
+						Scheduled: curr.ImportPolicy.Scheduled,
247 248
 					},
248 249
 				}
249 250
 				if curr.Generation != nil {
... ...
@@ -271,7 +272,8 @@ func init() {
271 271
 					Annotations: newTagReference.Annotations,
272 272
 					Reference:   newTagReference.Reference,
273 273
 					ImportPolicy: TagImportPolicy{
274
-						Insecure: newTagReference.ImportPolicy.Insecure,
274
+						Insecure:  newTagReference.ImportPolicy.Insecure,
275
+						Scheduled: newTagReference.ImportPolicy.Scheduled,
275 276
 					},
276 277
 				}
277 278
 				if newTagReference.Generation != nil {
... ...
@@ -85,6 +85,8 @@ type NamedTagReference struct {
85 85
 type TagImportPolicy struct {
86 86
 	// Insecure is true if the server may bypass certificate verification or connect directly over HTTP during image import.
87 87
 	Insecure bool `json:"insecure,omitempty" description:"if true, the server may bypass certificate verification or connect directly over HTTP during image import"`
88
+	// Scheduled indicates to the server that this tag should be periodically checked to ensure it is up to date, and imported
89
+	Scheduled bool `json:"scheduled,omitempty" description:"if true, the server will periodically check to ensure this tag is up to date"`
88 90
 }
89 91
 
90 92
 // ImageStreamStatus contains information about the state of this image stream.
... ...
@@ -95,7 +95,14 @@ func ValidateImageStream(stream *api.ImageStream) field.ErrorList {
95 95
 	for tag, tagRef := range stream.Spec.Tags {
96 96
 		if tagRef.From != nil {
97 97
 			switch tagRef.From.Kind {
98
-			case "DockerImage", "ImageStreamImage", "ImageStreamTag":
98
+			case "DockerImage":
99
+				if ref, err := api.ParseDockerImageReference(stream.Spec.DockerImageRepository); err == nil && tagRef.ImportPolicy.Scheduled && len(ref.ID) > 0 {
100
+					result = append(result, field.Invalid(field.NewPath("spec", "tags").Key(tag).Child("from", "name"), tagRef.From.Name, "only tags can be scheduled for import"))
101
+				}
102
+			case "ImageStreamImage", "ImageStreamTag":
103
+				if tagRef.ImportPolicy.Scheduled {
104
+					result = append(result, field.Invalid(field.NewPath("spec", "tags").Key(tag).Child("importPolicy", "scheduled"), tagRef.ImportPolicy.Scheduled, "only tags pointing to Docker repositories may be scheduled for background import"))
105
+				}
99 106
 			default:
100 107
 				result = append(result, field.Invalid(field.NewPath("spec", "tags").Key(tag).Child("from", "kind"), tagRef.From.Kind, "valid values are 'DockerImage', 'ImageStreamImage', 'ImageStreamTag'"))
101 108
 			}
... ...
@@ -191,8 +198,12 @@ func ValidateImageStreamImport(isi *api.ImageStreamImport) field.ErrorList {
191 191
 			if len(spec.From.Name) == 0 {
192 192
 				errs = append(errs, field.Required(imagesPath.Index(i).Child("from", "name")))
193 193
 			} else {
194
-				if _, err := api.ParseDockerImageReference(spec.From.Name); err != nil {
194
+				if ref, err := api.ParseDockerImageReference(spec.From.Name); err != nil {
195 195
 					errs = append(errs, field.Invalid(imagesPath.Index(i).Child("from", "name"), spec.From.Name, err.Error()))
196
+				} else {
197
+					if len(ref.ID) > 0 && spec.ImportPolicy.Scheduled {
198
+						errs = append(errs, field.Invalid(imagesPath.Index(i).Child("from", "name"), spec.From.Name, "only tags can be scheduled for import"))
199
+					}
196 200
 				}
197 201
 			}
198 202
 		default:
... ...
@@ -207,8 +218,12 @@ func ValidateImageStreamImport(isi *api.ImageStreamImport) field.ErrorList {
207 207
 			if len(spec.From.Name) == 0 {
208 208
 				errs = append(errs, field.Required(repoPath.Child("from", "name")))
209 209
 			} else {
210
-				if _, err := api.ParseDockerImageReference(spec.From.Name); err != nil {
211
-					errs = append(errs, field.Invalid(repoPath.Child("from", "name"), spec.From.Name, err.Error()))
210
+				if ref, err := api.ParseDockerImageReference(from.Name); err != nil {
211
+					errs = append(errs, field.Invalid(repoPath.Child("from", "name"), from.Name, err.Error()))
212
+				} else {
213
+					if len(ref.ID) > 0 || len(ref.Tag) > 0 {
214
+						errs = append(errs, field.Invalid(repoPath.Child("from", "name"), from.Name, "you must specify an image repository, not a tag or ID"))
215
+					}
212 216
 				}
213 217
 			}
214 218
 		default:
... ...
@@ -276,6 +276,29 @@ func TestValidateImageStream(t *testing.T) {
276 276
 				field.Required(field.NewPath("status", "tags").Key("tag").Child("items").Index(2).Child("dockerImageReference")),
277 277
 			},
278 278
 		},
279
+		"only DockerImage tags can be scheduled": {
280
+			namespace: "namespace",
281
+			name:      "foo",
282
+			specTags: map[string]api.TagReference{
283
+				"tag": {
284
+					From: &kapi.ObjectReference{
285
+						Kind: "DockerImage",
286
+						Name: "abc",
287
+					},
288
+					ImportPolicy: api.TagImportPolicy{Scheduled: true},
289
+				},
290
+				"other": {
291
+					From: &kapi.ObjectReference{
292
+						Kind: "ImageStreamTag",
293
+						Name: "other:latest",
294
+					},
295
+					ImportPolicy: api.TagImportPolicy{Scheduled: true},
296
+				},
297
+			},
298
+			expected: field.ErrorList{
299
+				field.Invalid(field.NewPath("spec", "tags").Key("other").Child("importPolicy", "scheduled"), true, "only tags pointing to Docker repositories may be scheduled for background import"),
300
+			},
301
+		},
279 302
 		"valid": {
280 303
 			namespace: "namespace",
281 304
 			name:      "foo",