func TestBeginLocalACI(t *testing.T) { manblob, err := json.Marshal(detailedManifest()) if err != nil { panic(err) } tmpexpandedaci := mustTempDir() defer os.RemoveAll(tmpexpandedaci) err = ioutil.WriteFile(path.Join(tmpexpandedaci, aci.ManifestFile), manblob, 0644) if err != nil { panic(err) } err = os.Mkdir(path.Join(tmpexpandedaci, aci.RootfsDir), 0755) if err != nil { panic(err) } tmpaci, err := ioutil.TempFile("", "acbuild-test") if err != nil { panic(err) } defer os.RemoveAll(tmpaci.Name()) aw := aci.NewImageWriter(detailedManifest(), tar.NewWriter(tmpaci)) err = filepath.Walk(tmpexpandedaci, aci.BuildWalker(tmpexpandedaci, aw, nil)) aw.Close() if err != nil { panic(err) } tmpaci.Close() workingDir := mustTempDir() defer cleanUpTest(workingDir) _, _, _, err = runACBuild(workingDir, "begin", tmpaci.Name()) if err != nil { t.Fatalf("%s\n", err.Error()) } checkManifest(t, workingDir, detailedManifest()) checkEmptyRootfs(t, workingDir) }
// Write will produce the resulting ACI from the current build context, saving // it to the given path, optionally signing it. func (a *ACBuild) Write(output string, overwrite, sign bool, gpgflags []string) (err error) { if err = a.lock(); err != nil { return err } defer func() { if err1 := a.unlock(); err == nil { err = err1 } }() man, err := util.GetManifest(a.CurrentACIPath) if err != nil { return err } if man.App != nil && len(man.App.Exec) == 0 { fmt.Fprintf(os.Stderr, "warning: exec command was never set.\n") } if man.Name == types.ACIdentifier(placeholdername) { return fmt.Errorf("can't write ACI, name was never set") } fileFlags := os.O_CREATE | os.O_WRONLY _, err = os.Stat(output) switch { case os.IsNotExist(err): break case err != nil: return err default: if !overwrite { return fmt.Errorf("ACI already exists: %s", output) } fileFlags |= os.O_TRUNC } // open/create the aci file ofile, err := os.OpenFile(output, fileFlags, 0644) if err != nil { return err } defer ofile.Close() defer func() { // When write is done, if an error is encountered remove the partial // ACI that had been written. if err != nil { os.Remove(output) os.Remove(output + ".asc") } }() // setup compression gzwriter := gzip.NewWriter(ofile) defer gzwriter.Close() // create the aci writer aw := aci.NewImageWriter(*man, tar.NewWriter(gzwriter)) err = filepath.Walk(a.CurrentACIPath, aci.BuildWalker(a.CurrentACIPath, aw, nil)) defer aw.Close() if err != nil { pathErr, ok := err.(*os.PathError) if !ok { fmt.Printf("not a path error!\n") return err } syscallErrno, ok := pathErr.Err.(syscall.Errno) if !ok { fmt.Printf("not a syscall errno!\n") return err } if pathErr.Op == "open" && syscallErrno != syscall.EACCES { return err } problemPath := pathErr.Path[len(path.Join(a.CurrentACIPath, aci.RootfsDir)):] return fmt.Errorf("%q: permission denied - call write as root", problemPath) } if sign { err = signACI(output, output+".asc", gpgflags) if err != nil { return err } } return nil }
func TestBeginLocalACI(t *testing.T) { wim := schema.ImageManifest{ ACKind: schema.ImageManifestKind, ACVersion: schema.AppContainerVersion, Name: *types.MustACIdentifier("acbuild-begin-test"), Labels: types.Labels{ types.Label{ Name: *types.MustACIdentifier("version"), Value: "9001", }, }, App: &types.App{ Exec: types.Exec{"/bin/nethack4", "-D", "wizard"}, User: "******", Group: "0", Environment: types.Environment{ types.EnvironmentVariable{ Name: "FOO", Value: "BAR", }, }, MountPoints: []types.MountPoint{ types.MountPoint{ Name: *types.MustACName("nethack4-data"), Path: "/root/nethack4-data", ReadOnly: true, }, }, Ports: []types.Port{ types.Port{ Name: *types.MustACName("gopher"), Protocol: "tcp", Port: 70, Count: 1, }, }, }, Annotations: types.Annotations{ types.Annotation{ Name: *types.MustACIdentifier("author"), Value: "the acbuild devs", }, }, Dependencies: types.Dependencies{ types.Dependency{ ImageName: *types.MustACIdentifier("quay.io/gnu/hurd"), }, }, } manblob, err := wim.MarshalJSON() if err != nil { panic(err) } tmpexpandedaci := mustTempDir() defer os.RemoveAll(tmpexpandedaci) err = ioutil.WriteFile(path.Join(tmpexpandedaci, aci.ManifestFile), manblob, 0644) if err != nil { panic(err) } err = os.Mkdir(path.Join(tmpexpandedaci, aci.RootfsDir), 0755) if err != nil { panic(err) } tmpaci, err := ioutil.TempFile("", "acbuild-test") if err != nil { panic(err) } defer os.RemoveAll(tmpaci.Name()) aw := aci.NewImageWriter(wim, tar.NewWriter(tmpaci)) err = filepath.Walk(tmpexpandedaci, aci.BuildWalker(tmpexpandedaci, aw, nil)) aw.Close() if err != nil { panic(err) } tmpaci.Close() tmpdir := mustTempDir() defer cleanUpTest(tmpdir) err = runAcbuild(tmpdir, "begin", tmpaci.Name()) if err != nil { t.Fatalf("%v", err) } checkMinimalContainer(t, path.Join(tmpdir, ".acbuild", "currentaci"), wim) }
// Write will produce the resulting ACI from the current build context, saving // it to the given path, optionally signing it. func (a *ACBuild) Write(output string, overwrite, sign bool, gpgflags []string) (err error) { if err = a.lock(); err != nil { return err } defer func() { if err1 := a.unlock(); err == nil { err = err1 } }() man, err := util.GetManifest(a.CurrentACIPath) if err != nil { return err } if man.App != nil && len(man.App.Exec) == 0 { fmt.Fprintf(os.Stderr, "warning: exec command was never set.\n") } if man.Name == types.ACIdentifier(placeholdername) { return fmt.Errorf("can't write ACI, name was never set") } fileFlags := os.O_CREATE | os.O_WRONLY ex, err := util.Exists(output) if err != nil { return err } if ex { if !overwrite { return fmt.Errorf("ACI already exists: %s", output) } fileFlags |= os.O_TRUNC } // open/create the aci file ofile, err := os.OpenFile(output, fileFlags, 0644) if err != nil { return err } defer ofile.Close() // setup compression gzwriter := gzip.NewWriter(ofile) defer gzwriter.Close() // create the aci writer aw := aci.NewImageWriter(*man, tar.NewWriter(gzwriter)) err = filepath.Walk(a.CurrentACIPath, aci.BuildWalker(a.CurrentACIPath, aw, nil)) defer aw.Close() if err != nil { return err } if sign { err = signACI(output, output+".asc", gpgflags) if err != nil { os.Remove(output) os.Remove(output + ".asc") return err } } return nil }