func (cnt *Img) runBuildLate() { res, err := utils.IsDirEmpty(cnt.target + PATH_RUNLEVELS + PATH_BUILD_LATE) res2, err2 := utils.IsDirEmpty(cnt.rootfs + PATH_CNT + PATH_RUNLEVELS + PATH_INHERIT_BUILD_LATE) if (res && res2) || (err != nil && err2 != nil) { return } { rootfs := "${TARGET}/rootfs" if cnt.manifest.Build.NoBuildImage() { rootfs = "" } build := strings.Replace(BUILD_SCRIPT_LATE, "%%ROOTFS%%", rootfs, 1) ioutil.WriteFile(cnt.target+"/build-late.sh", []byte(build), 0777) } if err := utils.ExecCmd("systemd-nspawn", "--version"); err == nil { log.Info("Run with systemd-nspawn") if err := utils.ExecCmd("systemd-nspawn", "--directory="+cnt.rootfs, "--capability=all", "--bind="+cnt.target+"/:/target", "target/build-late.sh"); err != nil { panic("Build step did not succeed" + err.Error()) } } else { panic("systemd-nspawn is required") } }
func (cnt *Img) Test() { cnt.Install() log.Info("Testing " + cnt.manifest.NameAndVersion) if _, err := os.Stat(cnt.path + PATH_TESTS); err != nil { if cnt.args.NoTestFail { panic("Test directory does not exists but tests are mandatory") } log.Warn("Tests directory does not exists") return } cnt.importAciBats() testAci, err := cnt.prepareTestAci() if err != nil { panic(err) } testAci.Build() os.MkdirAll(cnt.target+PATH_TESTS+PATH_TARGET+PATH_RESULT, 0777) if err := utils.ExecCmd("rkt", "--insecure-skip-verify=true", "run", "--mds-register=false", "--no-overlay=true", "--volume=result,kind=host,source="+cnt.target+PATH_TESTS+PATH_TARGET+PATH_RESULT, cnt.target+PATH_TESTS+PATH_TARGET+"/image.aci"); err != nil { // rkt+systemd cannot exit with fail status yet panic(err) } cnt.checkResult() }
func (p *Pod) Push() { log.Info("Push POD", p.manifest.Name) p.Build() checkVersion := make(chan bool, 1) for _, e := range p.manifest.Pod.Apps { aci, err := NewAciWithManifest(p.path+"/"+e.Name, p.args, p.toAciManifest(e), &checkVersion) if err != nil { panic(err) } aci.PodName = &p.manifest.Name aci.Push() } for range p.manifest.Pod.Apps { <-checkVersion } if err := utils.ExecCmd("curl", "-i", "-F", "r=releases", "-F", "hasPom=false", "-F", "e=service", "-F", "g=com.blablacar.aci.linux.amd64", "-F", "p=service", "-F", "v="+p.manifest.Name.Version(), "-F", "a="+p.manifest.Name.ShortName(), "-F", "file=@"+p.target+"/"+p.manifest.Name.ShortName()+"@.service", "-u", config.GetConfig().Push.Username+":"+config.GetConfig().Push.Password, config.GetConfig().Push.Url+"/service/local/artifact/maven/content"); err != nil { panic("Cannot push pod" + err.Error()) } }
func (cnt *Img) copyInternals() { log.Info("Copy internals") os.MkdirAll(cnt.rootfs+PATH_CNT+PATH_BIN, 0755) os.MkdirAll(cnt.rootfs+"/bin", 0755) // this is required or systemd-nspawn will create symlink on it os.MkdirAll(cnt.rootfs+"/usr/bin", 0755) // this is required by systemd-nspawn busybox, _ := dist.Asset("dist/bindata/busybox") if err := ioutil.WriteFile(cnt.rootfs+PATH_CNT+PATH_BIN+"/busybox", busybox, 0777); err != nil { panic(err) } confd, _ := dist.Asset("dist/bindata/confd") if err := ioutil.WriteFile(cnt.rootfs+PATH_CNT+PATH_BIN+"/confd", confd, 0777); err != nil { panic(err) } attributeMerger, _ := dist.Asset("dist/bindata/attributes-merger") if err := ioutil.WriteFile(cnt.rootfs+PATH_CNT+PATH_BIN+"/attributes-merger", attributeMerger, 0777); err != nil { panic(err) } confdFile := `backend = "env" confdir = "/cnt" prefix = "/confd" log-level = "debug" ` os.MkdirAll(cnt.rootfs+PATH_CNT+"/prestart", 0755) if err := ioutil.WriteFile(cnt.rootfs+PATH_CNT+"/prestart/confd.toml", []byte(confdFile), 0777); err != nil { panic(err) } if err := ioutil.WriteFile(cnt.rootfs+PATH_CNT+PATH_BIN+"/prestart", []byte(PRESTART), 0777); err != nil { panic(err) } }
func (p *Pod) Graph() { log.Info("Graph POD", p.manifest.Name) os.MkdirAll(p.target, 0777) var buffer bytes.Buffer buffer.WriteString("digraph {\n") buffer.WriteString(" {\n") buffer.WriteString(" ") buffer.WriteString("\"") buffer.WriteString(p.manifest.Name.ShortNameId()) buffer.WriteString("\"") buffer.WriteString(" [style=filled, fillcolor=yellow, shape=box]\n") buffer.WriteString(" }\n") for _, e := range p.manifest.Pod.Apps { for _, d := range e.Dependencies { buffer.WriteString(" ") buffer.WriteString("\"") buffer.WriteString(d.ShortNameId()) buffer.WriteString("\"") buffer.WriteString(" -> ") buffer.WriteString("\"") buffer.WriteString(p.manifest.Name.ShortNameId()) buffer.WriteString("\"") buffer.WriteString("\n") } } buffer.WriteString("}\n") ioutil.WriteFile(p.target+"/graph.dot", buffer.Bytes(), 0644) }
func (cnt *Img) Clean() { log.Info("Cleaning " + cnt.manifest.NameAndVersion) checkVersion := make(chan bool, 1) go cnt.checkLatestVersions(&checkVersion) if err := os.RemoveAll(cnt.target + "/"); err != nil { panic("Cannot clean " + cnt.manifest.NameAndVersion.String() + err.Error()) } <-checkVersion }
func (p *Pod) Build() { log.Info("Building POD : ", p.manifest.Name) os.RemoveAll(p.target) os.MkdirAll(p.target, 0777) apps := p.processAci() p.writeSystemdUnit(apps) }
func (cnt *Img) copyRunlevelsScripts() { log.Info("Copy Runlevels scripts") utils.CopyDir(cnt.path+PATH_RUNLEVELS+PATH_BUILD, cnt.target+PATH_RUNLEVELS+PATH_BUILD) utils.CopyDir(cnt.path+PATH_RUNLEVELS+PATH_BUILD_LATE, cnt.target+PATH_RUNLEVELS+PATH_BUILD_LATE) utils.CopyDir(cnt.path+PATH_RUNLEVELS+PATH_BUILD_SETUP, cnt.target+PATH_RUNLEVELS+PATH_BUILD_SETUP) utils.CopyDir(cnt.path+PATH_RUNLEVELS+PATH_PRESTART_EARLY, cnt.target+PATH_RUNLEVELS+PATH_PRESTART_EARLY) utils.CopyDir(cnt.path+PATH_RUNLEVELS+PATH_PRESTART_LATE, cnt.target+PATH_RUNLEVELS+PATH_PRESTART_LATE) utils.CopyDir(cnt.path+PATH_RUNLEVELS+PATH_PRESTART_EARLY, cnt.target+PATH_ROOTFS+PATH_CNT+PATH_RUNLEVELS+PATH_PRESTART_EARLY) utils.CopyDir(cnt.path+PATH_RUNLEVELS+PATH_PRESTART_LATE, cnt.target+PATH_ROOTFS+PATH_CNT+PATH_RUNLEVELS+PATH_PRESTART_LATE) utils.CopyDir(cnt.path+PATH_RUNLEVELS+PATH_INHERIT_BUILD_EARLY, cnt.target+PATH_ROOTFS+PATH_CNT+PATH_RUNLEVELS+PATH_INHERIT_BUILD_EARLY) utils.CopyDir(cnt.path+PATH_RUNLEVELS+PATH_INHERIT_BUILD_LATE, cnt.target+PATH_ROOTFS+PATH_CNT+PATH_RUNLEVELS+PATH_INHERIT_BUILD_LATE) }
func Execute() { log.Logger = logger.NewLogger() checkRktVersion() var rootCmd = &cobra.Command{Use: "cnt"} rootCmd.PersistentFlags().BoolVarP(&buildArgs.Clean, "clean", "c", false, "Clean before doing anything") rootCmd.PersistentFlags().StringVarP(&buildArgs.TargetPath, "target-path", "p", "", "Set target path") rootCmd.AddCommand(buildCmd, cleanCmd, pushCmd, installCmd, testCmd, versionCmd, initCmd, updateCmd, graphCmd) config.GetConfig().Load() rootCmd.Execute() log.Info("Victory !") }
func (cnt *Img) runLevelBuildSetup() { files, err := ioutil.ReadDir(cnt.path + PATH_RUNLEVELS + PATH_BUILD_SETUP) if err != nil { return } os.Setenv("BASEDIR", cnt.path) os.Setenv("TARGET", cnt.target) for _, f := range files { if !f.IsDir() { log.Info("Running Build setup level : ", f.Name()) if err := utils.ExecCmd(cnt.path + PATH_RUNLEVELS + PATH_BUILD_SETUP + "/" + f.Name()); err != nil { panic(err) } } } }
func (cnt *Img) UpdateConf() error { log.Info("Updating Image : ", cnt.manifest.NameAndVersion) os.MkdirAll(cnt.rootfs, 0777) cnt.writeImgManifest() cnt.writeCntManifest() // TODO move that, here because we update the version number to generated version cnt.copyRunlevelsScripts() cnt.copyAttributes() cnt.copyConfd() cnt.copyFiles() cnt.tarAci(false) return nil }
func (p *Pod) Test() { log.Info("Testing POD", p.manifest.Name) checkVersion := make(chan bool, 1) for _, e := range p.manifest.Pod.Apps { aci, err := NewAciWithManifest(p.path+"/"+e.Name, p.args, p.toAciManifest(e), &checkVersion) if err != nil { panic(err) } aci.PodName = &p.manifest.Name aci.Test() } for range p.manifest.Pod.Apps { <-checkVersion } }
func (cnt *Img) Graph() { log.Info("Graph " + cnt.manifest.NameAndVersion) os.MkdirAll(cnt.target, 0777) var buffer bytes.Buffer buffer.WriteString("digraph {\n") if cnt.manifest.From != "" { buffer.WriteString(" ") buffer.WriteString("\"") buffer.WriteString(cnt.manifest.From.ShortNameId()) buffer.WriteString("\"") buffer.WriteString(" -> ") buffer.WriteString("\"") buffer.WriteString(cnt.manifest.NameAndVersion.ShortNameId()) buffer.WriteString("\"") buffer.WriteString("[color=red,penwidth=2.0]") buffer.WriteString("\n") } for _, dep := range cnt.manifest.Aci.Dependencies { buffer.WriteString(" ") buffer.WriteString("\"") buffer.WriteString(dep.ShortNameId()) buffer.WriteString("\"") buffer.WriteString(" -> ") buffer.WriteString("\"") buffer.WriteString(cnt.manifest.NameAndVersion.ShortNameId()) buffer.WriteString("\"") buffer.WriteString("\n") } buffer.WriteString("}\n") ioutil.WriteFile(cnt.target+"/graph.dot", buffer.Bytes(), 0644) }
func (cnt *Img) Build() error { log.Info("Building Image : ", cnt.manifest.NameAndVersion) os.MkdirAll(cnt.rootfs, 0777) cnt.processFrom() cnt.copyInternals() cnt.copyRunlevelsScripts() cnt.runLevelBuildSetup() cnt.writeImgManifest() cnt.writeCntManifest() // TODO move that, here because we update the version number to generated version cnt.runBuild() cnt.copyAttributes() cnt.copyConfd() cnt.copyFiles() cnt.runBuildLate() cnt.tarAci(false) // ExecCmd("chown " + os.Getenv("SUDO_USER") + ": " + target + "/*") //TODO chown return nil }
func (cnt *Img) Init() { initPath := cnt.path if cnt.args.Path != "" { initPath = cnt.args.Path } log.Info("Setting up files three") uid := "0" gid := "0" if os.Getenv("SUDO_UID") != "" { uid = os.Getenv("SUDO_UID") gid = os.Getenv("SUDO_GID") } files := make(map[string]string) files[PATH_RUNLEVELS+PATH_PRESTART_EARLY+"/10.prestart-early.sh"] = `#!/cnt/bin/busybox sh echo "I'm a prestart early script that is run before templating" ` files[PATH_RUNLEVELS+PATH_PRESTART_LATE+"/10.prestart-late.sh"] = `#!/cnt/bin/busybox sh echo "I'm a prestart late script that is run after templating" ` files[PATH_RUNLEVELS+PATH_BUILD+"/10.install.sh"] = `#!/cnt/bin/busybox sh echo "I'm a build script that is run to install applications" ` files[PATH_RUNLEVELS+PATH_BUILD_SETUP+"/10.setup.sh"] = `#!/bin/sh echo "I'm build setup script file that is run from $BASEDIR to prepare $TARGET/rootfs before running build scripts" ` files[PATH_RUNLEVELS+PATH_BUILD_LATE+"/10.setup.sh"] = `#!/cnt/bin/busybox sh echo "I'm a build late script that is run to install applications after the copy of files,template,etc..." ` files[PATH_RUNLEVELS+PATH_INHERIT_BUILD_EARLY+"/10.inherit-build-early.sh"] = `#!/cnt/bin/busybox sh echo "I'm a inherit build early script that is run on this image and all images that have me as From during build" ` files[PATH_RUNLEVELS+PATH_INHERIT_BUILD_LATE+"/10.inherit-build-early.sh"] = `#!/cnt/bin/busybox sh echo "I'm a inherit build late script that is run on this image and all images that have me as From during build" ` files[PATH_FILES+"/dummy"] = `Dummy file ` files[PATH_ATTRIBUTES+"/attributes.yml"] = `default: dummy: world ` files[PATH_CONFD+PATH_CONFDOTD+"/templated.toml"] = `[template] src = "templated.tmpl" dest = "/templated" uid = 0 gid = 0 mode = "0644" keys = ["/"] ` files[PATH_CONFD+PATH_TEMPLATES+"/templated.tmpl"] = `{{$data := json (getv "/data")}}Hello {{ $data.dummy }} ` files[".gitignore"] = `target/ ` files["cnt-manifest.yml"] = `from: "" name: aci.example.com/aci-dummy:1 aci: app: exec: [ "/cnt/bin/busybox", "sh" ] eventHandlers: - { name: pre-start, exec: [ "/cnt/bin/prestart" ] } ` files[PATH_TESTS+"/dummy.bats"] = `#!/cnt/bin/bats -x @test "Prestart should template" { result="$(cat /templated)" [ "$result" == "Hello world" ] } @test "Cnt should copy files" { result="$(cat /dummy)" [ "$result" == "Dummy file" ] } ` files[PATH_TESTS+"/wait.sh"] = `exit 0` for filePath, data := range files { fpath := initPath + "/" + filePath os.MkdirAll(filepath.Dir(fpath), 0777) ioutil.WriteFile(fpath, []byte(data), 0777) } utils.ExecCmd("chown", "-R", uid+":"+gid, initPath) }