func validatePodAnnotations(metadataURL string, pm *schema.PodManifest) results { r := results{} var actualAnnots types.Annotations annots, err := metadataGet(metadataURL, "/pod/annotations/") if err != nil { return append(r, err) } for _, key := range strings.Split(string(annots), "\n") { if key == "" { continue } val, err := metadataGet(metadataURL, "/pod/annotations/"+key) if err != nil { r = append(r, err) } name, err := types.NewACIdentifier(key) if err != nil { r = append(r, fmt.Errorf("invalid annotation name: %v", err)) continue } actualAnnots.Set(*name, string(val)) } if !reflect.DeepEqual(actualAnnots, pm.Annotations) { r = append(r, fmt.Errorf("pod annotations mismatch: %v vs %v", actualAnnots, pm.Annotations)) } return r }
func mergeAppAnnotations(im *schema.ImageManifest, pm *schema.PodManifest, appName *types.ACName) types.Annotations { merged := types.Annotations{} for _, annot := range im.Annotations { merged.Set(annot.Name, annot.Value) } if app := pm.Apps.Get(*appName); app != nil { for _, annot := range app.Annotations { merged.Set(annot.Name, annot.Value) } } return merged }
func validateAppAnnotations(metadataURL string, pm *schema.PodManifest, app *schema.RuntimeApp, img *schema.ImageManifest) results { r := results{} // build a map of expected annotations by merging app.Annotations // with PodManifest overrides expectedAnnots := app.Annotations a := pm.Apps.Get(app.Name) if a == nil { panic("could not find app in manifest!") } for _, annot := range a.Annotations { expectedAnnots.Set(annot.Name, annot.Value) } var actualAnnots types.Annotations annots, err := metadataGet(metadataURL, "/apps/"+string(app.Name)+"/annotations/") if err != nil { return append(r, err) } for _, key := range strings.Split(string(annots), "\n") { if key == "" { continue } val, err := metadataGet(metadataURL, "/apps/"+string(app.Name)+"/annotations/"+key) if err != nil { r = append(r, err) } lbl, err := types.NewACIdentifier(key) if err != nil { r = append(r, fmt.Errorf("invalid annotation name: %v", err)) continue } actualAnnots.Set(*lbl, string(val)) } if !reflect.DeepEqual(actualAnnots, expectedAnnots) { err := fmt.Errorf("%v annotations mismatch: %v vs %v", app.Name, actualAnnots, expectedAnnots) r = append(r, err) } return r }
// GenerateManifest converts the docker manifest format to an appc // ImageManifest. func GenerateManifest(layerData types.DockerImageData, dockerURL *types.ParsedDockerURL) (*schema.ImageManifest, error) { dockerConfig := layerData.Config genManifest := &schema.ImageManifest{} appURL := "" appURL = dockerURL.IndexURL + "/" appURL += dockerURL.ImageName + "-" + layerData.ID appURL, err := appctypes.SanitizeACIdentifier(appURL) if err != nil { return nil, err } name := appctypes.MustACIdentifier(appURL) genManifest.Name = *name acVersion, err := appctypes.NewSemVer(schema.AppContainerVersion.String()) if err != nil { panic("invalid appc spec version") } genManifest.ACVersion = *acVersion genManifest.ACKind = appctypes.ACKind(schema.ImageManifestKind) var annotations appctypes.Annotations labels := make(map[appctypes.ACIdentifier]string) parentLabels := make(map[appctypes.ACIdentifier]string) addLabel := func(key, val string) { if key != "" && val != "" { labels[*appctypes.MustACIdentifier(key)] = val } } addParentLabel := func(key, val string) { if key != "" && val != "" { parentLabels[*appctypes.MustACIdentifier(key)] = val } } addAnno := func(key, val string) { if key != "" && val != "" { annotations.Set(*appctypes.MustACIdentifier(key), val) } } addLabel("layer", layerData.ID) addLabel("version", dockerURL.Tag) addLabel("os", layerData.OS) addParentLabel("os", layerData.OS) addLabel("arch", layerData.Architecture) addParentLabel("arch", layerData.OS) addAnno("authors", layerData.Author) epoch := time.Unix(0, 0) if !layerData.Created.Equal(epoch) { addAnno("created", layerData.Created.Format(time.RFC3339)) } addAnno("docker-comment", layerData.Comment) addAnno(common.AppcDockerRegistryURL, dockerURL.IndexURL) addAnno(common.AppcDockerRepository, dockerURL.ImageName) addAnno(common.AppcDockerImageID, layerData.ID) addAnno(common.AppcDockerParentImageID, layerData.Parent) if dockerConfig != nil { exec := getExecCommand(dockerConfig.Entrypoint, dockerConfig.Cmd) if exec != nil { user, group := parseDockerUser(dockerConfig.User) var env appctypes.Environment for _, v := range dockerConfig.Env { parts := strings.SplitN(v, "=", 2) env.Set(parts[0], parts[1]) } app := &appctypes.App{ Exec: exec, User: user, Group: group, Environment: env, WorkingDirectory: dockerConfig.WorkingDir, } app.MountPoints, err = convertVolumesToMPs(dockerConfig.Volumes) if err != nil { return nil, err } app.Ports, err = convertPorts(dockerConfig.ExposedPorts, dockerConfig.PortSpecs) if err != nil { return nil, err } ep, cmd, err := generateEPCmdAnnotation(dockerConfig.Entrypoint, dockerConfig.Cmd) if err != nil { return nil, err } if len(ep) > 0 { addAnno(common.AppcDockerEntrypoint, ep) } if len(cmd) > 0 { addAnno(common.AppcDockerCmd, cmd) } genManifest.App = app } } if layerData.Parent != "" { indexPrefix := "" // omit docker hub index URL in app name indexPrefix = dockerURL.IndexURL + "/" parentImageNameString := indexPrefix + dockerURL.ImageName + "-" + layerData.Parent parentImageNameString, err := appctypes.SanitizeACIdentifier(parentImageNameString) if err != nil { return nil, err } parentImageName := appctypes.MustACIdentifier(parentImageNameString) plbl, err := appctypes.LabelsFromMap(labels) if err != nil { return nil, err } genManifest.Dependencies = append(genManifest.Dependencies, appctypes.Dependency{ImageName: *parentImageName, Labels: plbl}) addAnno(common.AppcDockerTag, dockerURL.Tag) } genManifest.Labels, err = appctypes.LabelsFromMap(labels) if err != nil { return nil, err } genManifest.Annotations = annotations return genManifest, nil }