// GenerateParameterValues generates Value for each Parameter of the given // Template that has Generate field specified where Value is not already // supplied. // // Examples: // // from | value // ----------------------------- // "test[0-9]{1}x" | "test7x" // "[0-1]{8}" | "01001100" // "0x[A-F0-9]{4}" | "0xB3AF" // "[a-zA-Z0-9]{8}" | "hW4yQU5i" // If an error occurs, the parameter that caused the error is returned along with the error message. func (p *Processor) GenerateParameterValues(t *api.Template) *field.Error { for i := range t.Parameters { param := &t.Parameters[i] if len(param.Value) > 0 { continue } templatePath := field.NewPath("template").Child("parameters").Index(i) if param.Generate != "" { generator, ok := p.Generators[param.Generate] if !ok { return field.NotFound(templatePath, param) } if generator == nil { err := fmt.Errorf("template.parameters[%v]: Invalid '%v' generator for parameter %s", i, param.Generate, param.Name) return field.Invalid(templatePath, param, err.Error()) } value, err := generator.GenerateValue(param.From) if err != nil { return field.Invalid(templatePath, param, err.Error()) } param.Value, ok = value.(string) if !ok { err := fmt.Errorf("template.parameters[%v]: Unable to convert the generated value '%#v' to string for parameter %s", i, value, param.Name) return field.Invalid(templatePath, param, err.Error()) } } if len(param.Value) == 0 && param.Required { err := fmt.Errorf("template.parameters[%v]: parameter %s is required and must be specified", i, param.Name) return field.Required(templatePath, err.Error()) } } return nil }
// findStreamForMapping retrieves an ImageStream whose DockerImageRepository matches dockerRepo. func (s *REST) findStreamForMapping(ctx kapi.Context, mapping *api.ImageStreamMapping) (*api.ImageStream, error) { if len(mapping.Name) > 0 { return s.imageStreamRegistry.GetImageStream(ctx, mapping.Name) } if len(mapping.DockerImageRepository) != 0 { list, err := s.imageStreamRegistry.ListImageStreams(ctx, &kapi.ListOptions{}) if err != nil { return nil, err } for i := range list.Items { if mapping.DockerImageRepository == list.Items[i].Spec.DockerImageRepository { return &list.Items[i], nil } } return nil, errors.NewInvalid(api.Kind("ImageStreamMapping"), "", field.ErrorList{ field.NotFound(field.NewPath("dockerImageStream"), mapping.DockerImageRepository), }) } return nil, errors.NewNotFound(api.Resource("imagestream"), "") }
func TestNewInvalid(t *testing.T) { testCases := []struct { Err *field.Error Details *unversioned.StatusDetails }{ { field.Duplicate(field.NewPath("field[0].name"), "bar"), &unversioned.StatusDetails{ Kind: "kind", Name: "name", Causes: []unversioned.StatusCause{{ Type: unversioned.CauseTypeFieldValueDuplicate, Field: "field[0].name", }}, }, }, { field.Invalid(field.NewPath("field[0].name"), "bar", "detail"), &unversioned.StatusDetails{ Kind: "kind", Name: "name", Causes: []unversioned.StatusCause{{ Type: unversioned.CauseTypeFieldValueInvalid, Field: "field[0].name", }}, }, }, { field.NotFound(field.NewPath("field[0].name"), "bar"), &unversioned.StatusDetails{ Kind: "kind", Name: "name", Causes: []unversioned.StatusCause{{ Type: unversioned.CauseTypeFieldValueNotFound, Field: "field[0].name", }}, }, }, { field.NotSupported(field.NewPath("field[0].name"), "bar", nil), &unversioned.StatusDetails{ Kind: "kind", Name: "name", Causes: []unversioned.StatusCause{{ Type: unversioned.CauseTypeFieldValueNotSupported, Field: "field[0].name", }}, }, }, { field.Required(field.NewPath("field[0].name")), &unversioned.StatusDetails{ Kind: "kind", Name: "name", Causes: []unversioned.StatusCause{{ Type: unversioned.CauseTypeFieldValueRequired, Field: "field[0].name", }}, }, }, } for i, testCase := range testCases { vErr, expected := testCase.Err, testCase.Details expected.Causes[0].Message = vErr.ErrorBody() err := NewInvalid("kind", "name", field.ErrorList{vErr}) status := err.(*StatusError).ErrStatus if status.Code != 422 || status.Reason != unversioned.StatusReasonInvalid { t.Errorf("%d: unexpected status: %#v", i, status) } if !reflect.DeepEqual(expected, status.Details) { t.Errorf("%d: expected %#v, got %#v", i, expected, status.Details) } } }
// tagsChanged updates stream.Status.Tags based on the old and new image stream. // if the old stream is nil, all tags are considered additions. func (s Strategy) tagsChanged(old, stream *api.ImageStream) field.ErrorList { var errs field.ErrorList oldTags := map[string]api.TagReference{} if old != nil && old.Spec.Tags != nil { oldTags = old.Spec.Tags } for tag, tagRef := range stream.Spec.Tags { if oldRef, ok := oldTags[tag]; ok && !tagRefChanged(oldRef, tagRef, stream.Namespace) { continue } if tagRef.From == nil { continue } glog.V(5).Infof("Detected changed tag %s in %s/%s", tag, stream.Namespace, stream.Name) generation := stream.Generation tagRef.Generation = &generation fromPath := field.NewPath("spec", "tags").Key(tag).Child("from") if tagRef.From.Kind == "DockerImage" && len(tagRef.From.Name) > 0 { if tagRef.Reference { event, err := tagReferenceToTagEvent(stream, tagRef, "") if err != nil { errs = append(errs, field.Invalid(fromPath, tagRef.From, err.Error())) continue } stream.Spec.Tags[tag] = tagRef api.AddTagEventToImageStream(stream, tag, *event) } continue } tagRefStreamName, tagOrID, err := parseFromReference(stream, tagRef.From) if err != nil { errs = append(errs, field.Invalid(fromPath.Child("name"), tagRef.From.Name, "must be of the form <tag>, <repo>:<tag>, <id>, or <repo>@<id>")) continue } streamRef := stream streamRefNamespace := tagRef.From.Namespace if len(streamRefNamespace) == 0 { streamRefNamespace = stream.Namespace } if streamRefNamespace != stream.Namespace || tagRefStreamName != stream.Name { obj, err := s.ImageStreamGetter.Get(kapi.WithNamespace(kapi.NewContext(), streamRefNamespace), tagRefStreamName) if err != nil { if kerrors.IsNotFound(err) { errs = append(errs, field.NotFound(fromPath.Child("name"), tagRef.From.Name)) } else { errs = append(errs, field.Invalid(fromPath.Child("name"), tagRef.From.Name, fmt.Sprintf("unable to retrieve image stream: %v", err))) } continue } streamRef = obj.(*api.ImageStream) } event, err := tagReferenceToTagEvent(streamRef, tagRef, tagOrID) if err != nil { errs = append(errs, field.Invalid(fromPath.Child("name"), tagRef.From.Name, fmt.Sprintf("error generating tag event: %v", err))) continue } if event == nil { // referenced tag or ID doesn't exist, which is ok continue } stream.Spec.Tags[tag] = tagRef api.AddTagEventToImageStream(stream, tag, *event) } api.UpdateChangedTrackingTags(stream, old) // use a consistent timestamp on creation if old == nil && !stream.CreationTimestamp.IsZero() { for tag, list := range stream.Status.Tags { for _, event := range list.Items { event.Created = stream.CreationTimestamp } stream.Status.Tags[tag] = list } } return errs }