func TestVolumesToKvmDiskArgs(t *testing.T) { tests := []struct { volumes []types.Volume expected []string }{ { // one host volume - one argument volumes: []types.Volume{{Name: types.ACName("foo"), Kind: "host", Source: "src1"}}, expected: []string{"--9p=src1,foo"}, }, { // on empty volume - no arguments volumes: []types.Volume{{Name: types.ACName("foo"), Kind: "empty", Source: "src1"}}, expected: []string{}, }, { // two host volumes volumes: []types.Volume{ {Name: types.ACName("foo"), Kind: "host", Source: "src1"}, {Name: types.ACName("bar"), Kind: "host", Source: "src2"}, }, expected: []string{"--9p=src1,foo", "--9p=src2,bar"}, }, { // mix host and empty volumes: []types.Volume{ {Name: types.ACName("foo"), Kind: "host", Source: "src1"}, {Name: types.ACName("baz"), Kind: "empty", Source: "src1"}, {Name: types.ACName("bar"), Kind: "host", Source: "src2"}, }, expected: []string{"--9p=src1,foo", "--9p=src2,bar"}, }, } for i, tt := range tests { got := VolumesToKvmDiskArgs(tt.volumes) if len(got) != len(tt.expected) { t.Errorf("#%d: expected %v elements got %v", i, len(tt.expected), len(got)) } else { for iarg, argExpected := range tt.expected { if got[iarg] != argExpected { t.Errorf("#%d: arg %d expected `%v` got `%v`", i, iarg, argExpected, got[iarg]) } } } } }
func genManifest(path string) *schema.ImageManifest { // Get runtime.json and config.json runtimePath := path + "/runtime.json" configPath := path + "/config.json" runtime, err := ioutil.ReadFile(runtimePath) if err != nil { if debugEnabled { log.Printf("Open file runtime.json failed: %v", err) } return nil } config, err := ioutil.ReadFile(configPath) if err != nil { if debugEnabled { log.Printf("Open file config.json failed: %v", err) } return nil } var spec LinuxSpec err = json.Unmarshal(config, &spec) if err != nil { if debugEnabled { log.Printf("Unmarshal config.json failed: %v", err) } return nil } var runSpec LinuxRuntimeSpec err = json.Unmarshal(runtime, &runSpec) if err != nil { if debugEnabled { log.Printf("Unmarshal runtime.json failed: %v", err) } return nil } // Begin to convert runtime.json/config.json to manifest m := new(schema.ImageManifest) // 1. Assemble "acKind" field m.ACKind = "ImageManifest" // 2. Assemble "acVersion" field m.ACVersion = schema.AppContainerVersion // 3. Assemble "name" field m.Name = "oci" // 4. Assemble "labels" field // 4.1 "version" label := new(types.Label) label.Name = types.ACIdentifier("version") label.Value = spec.Version m.Labels = append(m.Labels, *label) // 4.2 "os" label = new(types.Label) label.Name = types.ACIdentifier("os") label.Value = spec.Platform.OS m.Labels = append(m.Labels, *label) // 4.3 "arch" label = new(types.Label) label.Name = types.ACIdentifier("arch") label.Value = spec.Platform.Arch m.Labels = append(m.Labels, *label) // 5. Assemble "app" field app := new(types.App) // 5.1 "exec" app.Exec = spec.Process.Args // 5.2 "user" app.User = fmt.Sprintf("%d", spec.Process.User.UID) // 5.3 "group" app.Group = fmt.Sprintf("%d", spec.Process.User.GID) // 5.4 "eventHandlers" event := new(types.EventHandler) event.Name = "pre-start" for index := range runSpec.Hooks.Prestart { event.Exec = append(event.Exec, runSpec.Hooks.Prestart[index].Path) event.Exec = append(event.Exec, runSpec.Hooks.Prestart[index].Args...) event.Exec = append(event.Exec, runSpec.Hooks.Prestart[index].Env...) } app.EventHandlers = append(app.EventHandlers, *event) event = new(types.EventHandler) event.Name = "post-stop" for index := range runSpec.Hooks.Poststop { event.Exec = append(event.Exec, runSpec.Hooks.Poststop[index].Path) event.Exec = append(event.Exec, runSpec.Hooks.Poststop[index].Args...) event.Exec = append(event.Exec, runSpec.Hooks.Poststop[index].Env...) } app.EventHandlers = append(app.EventHandlers, *event) // 5.5 "workingDirectory" app.WorkingDirectory = spec.Process.Cwd // 5.6 "environment" env := new(types.EnvironmentVariable) for index := range spec.Process.Env { s := strings.Split(spec.Process.Env[index], "=") env.Name = s[0] env.Value = s[1] app.Environment = append(app.Environment, *env) } // 5.7 "mountPoints" for index := range spec.Mounts { mount := new(types.MountPoint) mount.Name = types.ACName(spec.Mounts[index].Name) mount.Path = spec.Mounts[index].Path //mount.ReadOnly = true app.MountPoints = append(app.MountPoints, *mount) } // 5.8 "ports" // 5.9 "isolators" if runSpec.Linux.Resources != nil { if runSpec.Linux.Resources.CPU.Quota != 0 { cpuLimt := new(ResourceCPU) cpuLimt.Limit = fmt.Sprintf("%dm", runSpec.Linux.Resources.CPU.Quota) isolator := new(types.Isolator) isolator.Name = types.ACIdentifier("resource/cpu") bytes, _ := json.Marshal(cpuLimt) valueRaw := json.RawMessage(bytes) isolator.ValueRaw = &valueRaw app.Isolators = append(app.Isolators, *isolator) } if runSpec.Linux.Resources.Memory.Limit != 0 { memLimt := new(ResourceMem) memLimt.Limit = fmt.Sprintf("%dG", runSpec.Linux.Resources.Memory.Limit/(1024*1024*1024)) isolator := new(types.Isolator) isolator.Name = types.ACIdentifier("resource/memory") bytes, _ := json.Marshal(memLimt) valueRaw := json.RawMessage(bytes) isolator.ValueRaw = &valueRaw app.Isolators = append(app.Isolators, *isolator) } } if len(spec.Linux.Capabilities) != 0 { isolatorCapSet := new(IsolatorCapSet) isolatorCapSet.Sets = append(isolatorCapSet.Sets, spec.Linux.Capabilities...) isolator := new(types.Isolator) isolator.Name = types.ACIdentifier(types.LinuxCapabilitiesRetainSetName) bytes, _ := json.Marshal(isolatorCapSet) valueRaw := json.RawMessage(bytes) isolator.ValueRaw = &valueRaw app.Isolators = append(app.Isolators, *isolator) } // 6. "annotations" // 7. "dependencies" // 8. "pathWhitelist" m.App = app return m }
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=42"} patchImportAndFetchHash("rkt-inspect-print.aci", patches, t, ctx) // TODO(derekparker) There is a bug where `patchImportAndFetchHash` does not // return the full hash, which causes `InspectPod` to fail later in this test. // So instead we list images to get the full, correct hash. iresp, err := c.ListImages(context.Background(), &v1alpha.ListImagesRequest{}) if err != nil { t.Fatalf("Unexpected error: %v", err) } if len(iresp.Images) == 0 { t.Fatal("Expected non-zero images") } imgID, err := types.NewHash(iresp.Images[0].Id) if err != nil { t.Fatalf("Cannot generate types.Hash from %v: %v", iresp.Images[0].Id, err) } pm := schema.BlankPodManifest() pm.Apps = []schema.RuntimeApp{ schema.RuntimeApp{ Name: types.ACName("rkt-inspect"), Image: schema.RuntimeImage{ Name: types.MustACIdentifier("coreos.com/rkt-inspect"), ID: *imgID, }, Annotations: []types.Annotation{types.Annotation{Name: types.ACIdentifier("app-test"), Value: "app-test"}}, }, } pm.Annotations = []types.Annotation{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) esp := spawnOrFail(t, runCmd) waitOrFail(t, esp, true) // 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 { checkPodBasics(t, ctx, p) // 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) } }