func (img *Image) buildPodManifest(exec []string) *schema.PodManifest { bpm := schema.BlankPodManifest() // Figure out working path that doesn't exist in the image's rootfs workDir := ".jetpack.build." for { if _, err := os.Stat(img.getRootfs().Path(workDir)); err != nil { if os.IsNotExist(err) { break } panic(err) } workDir = fmt.Sprintf(".jetpack.build.%v", uuid.NewRandom()) } bprta := img.RuntimeApp() bprta.Name.Set("jetpack/build") bprta.App = &types.App{ Exec: exec, WorkingDirectory: "/" + workDir, User: "******", Group: "0", } bpm.Apps = append(bpm.Apps, bprta) // This is needed by freebsd-update at least, should be okay to // allow this in builders. bpm.Annotations.Set("jetpack/jail.conf/allow.chflags", "true") bpm.Annotations.Set("jetpack/jail.conf/securelevel", "0") return bpm }
func (s Service) podManifestToMap(result map[string][]cntspec.ACFullname, contents []byte) error { pod := schema.BlankPodManifest() err := pod.UnmarshalJSON(contents) if err != nil { return err } var podname string var acis []cntspec.ACFullname for i, podAci := range pod.Apps { version, _ := podAci.Image.Labels.Get("version") fullname := cntspec.NewACFullName(podAci.Image.Name.String() + ":" + version) if i == 0 { nameSplit := strings.SplitN(fullname.ShortName(), "_", 2) podname = fullname.DomainName() + "/" + nameSplit[0] } // resolved, err := fullname.FullyResolved() // TODO should not be resolved for local test ?? // if err != nil { // logrus.WithError(err).Fatal("Cannot fully resolve ACI") // } acis = append(acis, *fullname) } result[podname] = acis return nil }
// makePodManifest transforms a kubelet pod spec to the rkt pod manifest. // TODO(yifan): Use the RunContainerOptions generated by GenerateRunContainerOptions(). func (r *runtime) makePodManifest(pod *api.Pod) (*appcschema.PodManifest, error) { var globalPortMappings []kubecontainer.PortMapping manifest := appcschema.BlankPodManifest() for _, c := range pod.Spec.Containers { imgManifest, err := r.getImageManifest(c.Image) if err != nil { return nil, err } if imgManifest.App == nil { return nil, fmt.Errorf("no app section in image manifest for image: %q", c.Image) } img, err := r.getImageByName(c.Image) if err != nil { return nil, err } hash, err := appctypes.NewHash(img.id) if err != nil { return nil, err } opts, err := r.generator.GenerateRunContainerOptions(pod, &c) if err != nil { return nil, err } globalPortMappings = append(globalPortMappings, opts.PortMappings...) if err := setApp(imgManifest.App, &c, opts); err != nil { return nil, err } manifest.Apps = append(manifest.Apps, appcschema.RuntimeApp{ // TODO(yifan): We should allow app name to be different with // image name. See https://github.com/coreos/rkt/pull/640. Name: imgManifest.Name, Image: appcschema.RuntimeImage{ID: *hash}, App: imgManifest.App, }) } volumeMap, ok := r.volumeGetter.GetVolumes(pod.UID) if !ok { return nil, fmt.Errorf("cannot get the volumes for pod %q", kubecontainer.GetPodFullName(pod)) } // Set global volumes. for name, volume := range volumeMap { volName, err := appctypes.NewACName(name) if err != nil { return nil, fmt.Errorf("cannot use the volume's name %q as ACName: %v", name, err) } manifest.Volumes = append(manifest.Volumes, appctypes.Volume{ Name: *volName, Kind: "host", Source: volume.GetPath(), }) } // Set global ports. for _, port := range globalPortMappings { name, err := appctypes.SanitizeACName(port.Name) if err != nil { return nil, fmt.Errorf("cannot use the port's name %q as ACName: %v", port.Name, err) } portName := appctypes.MustACName(name) manifest.Ports = append(manifest.Ports, appctypes.ExposedPort{ Name: *portName, HostPort: uint(port.HostPort), }) } // TODO(yifan): Set pod-level isolators once it's supported in kubernetes. return manifest, nil }
// makePodManifest transforms a kubelet pod spec to the rkt pod manifest. func (r *runtime) makePodManifest(pod *api.Pod, pullSecrets []api.Secret) (*appcschema.PodManifest, error) { var globalPortMappings []kubecontainer.PortMapping manifest := appcschema.BlankPodManifest() for _, c := range pod.Spec.Containers { if err := r.imagePuller.PullImage(pod, &c, pullSecrets); err != nil { return nil, err } imgManifest, err := r.getImageManifest(c.Image) if err != nil { return nil, err } if imgManifest.App == nil { imgManifest.App = new(appctypes.App) } img, err := r.getImageByName(c.Image) if err != nil { return nil, err } hash, err := appctypes.NewHash(img.ID) if err != nil { return nil, err } opts, err := r.generator.GenerateRunContainerOptions(pod, &c) if err != nil { return nil, err } globalPortMappings = append(globalPortMappings, opts.PortMappings...) if err := setApp(imgManifest.App, &c, opts); err != nil { return nil, err } name, err := appctypes.SanitizeACName(c.Name) if err != nil { return nil, err } appName := appctypes.MustACName(name) manifest.Apps = append(manifest.Apps, appcschema.RuntimeApp{ Name: *appName, Image: appcschema.RuntimeImage{ID: *hash}, App: imgManifest.App, }) } volumeMap, ok := r.volumeGetter.GetVolumes(pod.UID) if !ok { return nil, fmt.Errorf("cannot get the volumes for pod %q", kubeletUtil.FormatPodName(pod)) } // Set global volumes. for name, volume := range volumeMap { volName, err := appctypes.NewACName(name) if err != nil { return nil, fmt.Errorf("cannot use the volume's name %q as ACName: %v", name, err) } manifest.Volumes = append(manifest.Volumes, appctypes.Volume{ Name: *volName, Kind: "host", Source: volume.GetPath(), }) } // Set global ports. for _, port := range globalPortMappings { name, err := appctypes.SanitizeACName(port.Name) if err != nil { return nil, fmt.Errorf("cannot use the port's name %q as ACName: %v", port.Name, err) } portName := appctypes.MustACName(name) manifest.Ports = append(manifest.Ports, appctypes.ExposedPort{ Name: *portName, HostPort: uint(port.HostPort), }) } // TODO(yifan): Set pod-level isolators once it's supported in kubernetes. return manifest, nil }
// makePodManifest transforms a kubelet pod spec to the rkt pod manifest. func (r *Runtime) makePodManifest(pod *api.Pod, pullSecrets []api.Secret) (*appcschema.PodManifest, error) { var globalPortMappings []kubecontainer.PortMapping manifest := appcschema.BlankPodManifest() listResp, err := r.apisvc.ListPods(context.Background(), &rktapi.ListPodsRequest{ Detail: true, Filters: kubernetesPodFilters(pod.UID), }) if err != nil { return nil, fmt.Errorf("couldn't list pods: %v", err) } restartCount := 0 for _, pod := range listResp.Pods { manifest := &appcschema.PodManifest{} err = json.Unmarshal(pod.Manifest, manifest) if err != nil { glog.Warningf("rkt: error unmatshaling pod manifest: %v", err) continue } if countString, ok := manifest.Annotations.Get(k8sRktRestartCountAnno); ok { num, err := strconv.Atoi(countString) if err != nil { glog.Warningf("rkt: error reading restart count on pod: %v", err) continue } if num+1 > restartCount { restartCount = num + 1 } } } manifest.Annotations.Set(*appctypes.MustACIdentifier(k8sRktKubeletAnno), k8sRktKubeletAnnoValue) manifest.Annotations.Set(*appctypes.MustACIdentifier(k8sRktUIDAnno), string(pod.UID)) manifest.Annotations.Set(*appctypes.MustACIdentifier(k8sRktNameAnno), pod.Name) manifest.Annotations.Set(*appctypes.MustACIdentifier(k8sRktNamespaceAnno), pod.Namespace) manifest.Annotations.Set(*appctypes.MustACIdentifier(k8sRktCreationTimeAnno), strconv.FormatInt(time.Now().Unix(), 10)) manifest.Annotations.Set(*appctypes.MustACIdentifier(k8sRktRestartCountAnno), strconv.Itoa(restartCount)) for _, c := range pod.Spec.Containers { app, portMappings, err := r.newAppcRuntimeApp(pod, c, pullSecrets) if err != nil { return nil, err } manifest.Apps = append(manifest.Apps, *app) globalPortMappings = append(globalPortMappings, portMappings...) } volumeMap, ok := r.volumeGetter.GetVolumes(pod.UID) if !ok { return nil, fmt.Errorf("cannot get the volumes for pod %q", format.Pod(pod)) } // Set global volumes. for vname, volume := range volumeMap { manifest.Volumes = append(manifest.Volumes, appctypes.Volume{ Name: convertToACName(vname), Kind: "host", Source: volume.Builder.GetPath(), }) } // Set global ports. for _, port := range globalPortMappings { manifest.Ports = append(manifest.Ports, appctypes.ExposedPort{ Name: convertToACName(port.Name), HostPort: uint(port.HostPort), }) } // TODO(yifan): Set pod-level isolators once it's supported in kubernetes. return manifest, nil }
func TestAPIServiceListInspectPods(t *testing.T) { ctx := testutils.NewRktRunCtx() defer ctx.Cleanup() svc := startAPIService(t, ctx) defer stopAPIService(t, svc) c, conn := newAPIClientOrFail(t, "localhost:15441") defer conn.Close() resp, err := c.ListPods(context.Background(), &v1alpha.ListPodsRequest{}) if err != nil { t.Fatalf("Unexpected error: %v", err) } if len(resp.Pods) != 0 { t.Errorf("Unexpected result: %v, should see zero pods", resp.Pods) } patches := []string{"--exec=/inspect --print-msg=HELLO_API --exit-code=0"} imageHash := patchImportAndFetchHash("rkt-inspect-print.aci", patches, t, ctx) imgID, err := types.NewHash(imageHash) if err != nil { t.Fatalf("Cannot generate types.Hash from %v: %v", imageHash, err) } pm := schema.BlankPodManifest() pm.Apps = []schema.RuntimeApp{ { Name: types.ACName("rkt-inspect"), Image: schema.RuntimeImage{ Name: types.MustACIdentifier("coreos.com/rkt-inspect"), ID: *imgID, }, Annotations: []types.Annotation{{Name: types.ACIdentifier("app-test"), Value: "app-test"}}, }, } pm.Annotations = []types.Annotation{{Name: types.ACIdentifier("test"), Value: "test"}} manifestFile := generatePodManifestFile(t, pm) defer os.Remove(manifestFile) runCmd := fmt.Sprintf("%s run --pod-manifest=%s", ctx.Cmd(), manifestFile) waitOrFail(t, spawnOrFail(t, runCmd), 0) gcCmd := fmt.Sprintf("%s gc --mark-only=true", ctx.Cmd()) waitOrFail(t, spawnOrFail(t, gcCmd), 0) gcTime := time.Now() // ListPods(detail=false). resp, err = c.ListPods(context.Background(), &v1alpha.ListPodsRequest{}) if err != nil { t.Fatalf("Unexpected error: %v", err) } if len(resp.Pods) == 0 { t.Errorf("Unexpected result: %v, should see non-zero pods", resp.Pods) } for _, p := range resp.Pods { checkPodBasicsWithGCTime(t, ctx, p, gcTime) // Test InspectPod(). inspectResp, err := c.InspectPod(context.Background(), &v1alpha.InspectPodRequest{Id: p.Id}) if err != nil { t.Fatalf("Unexpected error: %v", err) } checkPodDetails(t, ctx, inspectResp.Pod) // Test Apps. for i, app := range p.Apps { checkAnnotations(t, pm.Apps[i].Annotations, app.Annotations) } } // ListPods(detail=true). resp, err = c.ListPods(context.Background(), &v1alpha.ListPodsRequest{Detail: true}) if err != nil { t.Fatalf("Unexpected error: %v", err) } if len(resp.Pods) == 0 { t.Errorf("Unexpected result: %v, should see non-zero pods", resp.Pods) } for _, p := range resp.Pods { checkPodDetails(t, ctx, p) } }
type sliceFlag []string func (sf *sliceFlag) String() string { return fmt.Sprintf("%v", *sf) } func (sf *sliceFlag) Set(v string) error { *sf = append(*sf, v) return nil } // Command line flags used by different commands var SaveID string func SaveIDFlag(fl *flag.FlagSet) { fl.StringVar(&SaveID, "saveid", "", "Save ID to file") } var Quiet bool func QuietFlag(fl *flag.FlagSet, desc string) { fl.BoolVar(&Quiet, "q", false, fmt.Sprintf("quiet (%v)", desc)) } var thePodManifest = schema.BlankPodManifest() func flPodManifest(fl *flag.FlagSet) { acutil.PodManifestFlags(fl, thePodManifest) }