// CreateBaseCompilationImage will recompile the base BOSH image for a release func (f *Fissile) CreateBaseCompilationImage(baseImageName, repository, metricsPath string, keepContainer bool) error { if metricsPath != "" { stampy.Stamp(metricsPath, "fissile", "create-compilation-image", "start") defer stampy.Stamp(metricsPath, "fissile", "create-compilation-image", "done") } dockerManager, err := docker.NewImageManager() if err != nil { return fmt.Errorf("Error connecting to docker: %s", err.Error()) } baseImage, err := dockerManager.FindImage(baseImageName) if err != nil { return fmt.Errorf("Error looking up base image %s: %s", baseImageName, err) } f.UI.Println(color.GreenString("Base image with ID %s found", color.YellowString(baseImage.ID))) comp, err := compilator.NewCompilator(dockerManager, "", "", repository, compilation.UbuntuBase, f.Version, keepContainer, f.UI) if err != nil { return fmt.Errorf("Error creating a new compilator: %s", err.Error()) } if _, err := comp.CreateCompilationBase(baseImageName); err != nil { return fmt.Errorf("Error creating compilation base image: %s", err.Error()) } return nil }
func (j roleBuildJob) Run() { select { case <-j.abort: j.resultsCh <- nil return default: } roleImageName := GetRoleDevImageName(j.repository, j.role, j.role.GetRoleDevVersion()) if !j.force { if hasImage, err := j.dockerManager.HasImage(roleImageName); err != nil { j.resultsCh <- err return } else if hasImage { j.ui.Printf("Skipping build of role image %s because it exists\n", color.YellowString(j.role.Name)) j.resultsCh <- nil return } } if j.builder.metricsPath != "" { seriesName := fmt.Sprintf("create-role-images::%s", roleImageName) stampy.Stamp(j.builder.metricsPath, "fissile", seriesName, "start") defer stampy.Stamp(j.builder.metricsPath, "fissile", seriesName, "done") } j.ui.Printf("Creating Dockerfile for role %s ...\n", color.YellowString(j.role.Name)) dockerfileDir, err := j.builder.CreateDockerfileDir(j.role, j.baseImageName) if err != nil { j.resultsCh <- fmt.Errorf("Error creating Dockerfile and/or assets for role %s: %s", j.role.Name, err.Error()) return } if j.noBuild { j.ui.Printf("Skipping build of role image %s because of flag\n", color.YellowString(j.role.Name)) j.resultsCh <- nil return } if !strings.HasSuffix(dockerfileDir, string(os.PathSeparator)) { dockerfileDir = fmt.Sprintf("%s%c", dockerfileDir, os.PathSeparator) } j.ui.Printf("Building docker image of %s in %s ...\n", color.YellowString(j.role.Name), color.YellowString(dockerfileDir)) log := new(bytes.Buffer) stdoutWriter := docker.NewFormattingWriter( log, docker.ColoredBuildStringFunc(roleImageName), ) err = j.dockerManager.BuildImage(dockerfileDir, roleImageName, stdoutWriter) if err != nil { log.WriteTo(j.ui) j.resultsCh <- fmt.Errorf("Error building image: %s", err.Error()) return } j.resultsCh <- nil }
// GenerateBaseDockerImage generates a base docker image to be used as a FROM for role images func (f *Fissile) GenerateBaseDockerImage(targetPath, baseImage, metricsPath string, noBuild bool, repository string) error { if metricsPath != "" { stampy.Stamp(metricsPath, "fissile", "create-role-base", "start") defer stampy.Stamp(metricsPath, "fissile", "create-role-base", "done") } dockerManager, err := docker.NewImageManager() if err != nil { return fmt.Errorf("Error connecting to docker: %s", err.Error()) } baseImageName := builder.GetBaseImageName(repository, f.Version) image, err := dockerManager.FindImage(baseImageName) if err == docker.ErrImageNotFound { f.UI.Println("Image doesn't exist, it will be created ...") } else if err != nil { return fmt.Errorf("Error looking up image: %s", err.Error()) } else { f.UI.Println(color.GreenString( "Base role image %s with ID %s already exists. Doing nothing.", color.YellowString(baseImageName), color.YellowString(image.ID), )) return nil } if !strings.HasSuffix(targetPath, string(os.PathSeparator)) { targetPath = fmt.Sprintf("%s%c", targetPath, os.PathSeparator) } baseImageBuilder := builder.NewBaseImageBuilder(baseImage) if noBuild { f.UI.Println("Skipping image build because of flag.") return nil } f.UI.Println("Building base docker image ...") log := new(bytes.Buffer) stdoutWriter := docker.NewFormattingWriter( log, docker.ColoredBuildStringFunc(baseImageName), ) tarPopulator := baseImageBuilder.NewDockerPopulator() err = dockerManager.BuildImageFromCallback(baseImageName, stdoutWriter, tarPopulator) if err != nil { log.WriteTo(f.UI) return fmt.Errorf("Error building base image: %s", err) } f.UI.Println(color.GreenString("Done.")) return nil }
// GenerateRoleImages generates all role images using dev releases func (f *Fissile) GenerateRoleImages(targetPath, repository, metricsPath string, noBuild, force bool, workerCount int, rolesManifestPath, compiledPackagesPath, lightManifestPath, darkManifestPath string) error { if len(f.releases) == 0 { return fmt.Errorf("Releases not loaded") } if metricsPath != "" { stampy.Stamp(metricsPath, "fissile", "create-role-images", "start") defer stampy.Stamp(metricsPath, "fissile", "create-role-images", "done") } roleManifest, err := model.LoadRoleManifest(rolesManifestPath, f.releases) if err != nil { return fmt.Errorf("Error loading roles manifest: %s", err.Error()) } packagesImageBuilder, err := builder.NewPackagesImageBuilder( repository, compiledPackagesPath, targetPath, f.Version, f.UI, ) if err != nil { return err } err = f.GeneratePackagesRoleImage(repository, roleManifest, noBuild, force, packagesImageBuilder) if err != nil { return err } packagesLayerImageName := packagesImageBuilder.GetRolePackageImageName(roleManifest) roleBuilder, err := builder.NewRoleImageBuilder( repository, compiledPackagesPath, targetPath, lightManifestPath, darkManifestPath, metricsPath, "", f.Version, f.UI, ) if err != nil { return err } if err := roleBuilder.BuildRoleImages(roleManifest.Roles, repository, packagesLayerImageName, force, noBuild, workerCount); err != nil { return err } return nil }
// Compile will compile a list of dev BOSH releases func (f *Fissile) Compile(repository, targetPath, roleManifestPath, metricsPath string, workerCount int) error { if len(f.releases) == 0 { return fmt.Errorf("Releases not loaded") } if metricsPath != "" { stampy.Stamp(metricsPath, "fissile", "compile-packages", "start") defer stampy.Stamp(metricsPath, "fissile", "compile-packages", "done") } dockerManager, err := docker.NewImageManager() if err != nil { return fmt.Errorf("Error connecting to docker: %s", err.Error()) } roleManifest, err := model.LoadRoleManifest(roleManifestPath, f.releases) if err != nil { return fmt.Errorf("Error loading roles manifest: %s", err.Error()) } f.UI.Println(color.GreenString("Compiling packages for dev releases:")) for _, release := range f.releases { f.UI.Printf(" %s (%s)\n", color.YellowString(release.Name), color.MagentaString(release.Version)) } comp, err := compilator.NewCompilator(dockerManager, targetPath, metricsPath, repository, compilation.UbuntuBase, f.Version, false, f.UI) if err != nil { return fmt.Errorf("Error creating a new compilator: %s", err.Error()) } if err := comp.Compile(workerCount, f.releases, roleManifest); err != nil { return fmt.Errorf("Error compiling packages: %s", err.Error()) } return nil }
func (j compileJob) Run() { c := j.compilator // Metrics: Overall time for the specific job var waitSeriesName string var runSeriesName string if c.metricsPath != "" { seriesName := fmt.Sprintf("compile-packages::%s/%s", j.pkg.Release.Name, j.pkg.Name) waitSeriesName = fmt.Sprintf("compile-packages::wait::%s/%s", j.pkg.Release.Name, j.pkg.Name) runSeriesName = fmt.Sprintf("compile-packages::run::%s/%s", j.pkg.Release.Name, j.pkg.Name) stampy.Stamp(c.metricsPath, "fissile", seriesName, "start") defer stampy.Stamp(c.metricsPath, "fissile", seriesName, "done") stampy.Stamp(c.metricsPath, "fissile", waitSeriesName, "start") } // (xx) Wait for our deps. Note how without deps the killCh is // not checked and ignored. It is also in a race with (**) // draining doneCh and actually signaling the kill. // Time spent waiting for _, dep := range j.pkg.Dependencies { done := false for !done { select { case <-j.killCh: c.ui.Printf("killed: %s/%s\n", color.MagentaString(j.pkg.Release.Name), color.MagentaString(j.pkg.Name)) j.doneCh <- compileResult{pkg: j.pkg, err: errWorkerAbort} if c.metricsPath != "" { stampy.Stamp(c.metricsPath, "fissile", waitSeriesName, "done") } return case <-time.After(5 * time.Second): c.ui.Printf("waiting: %s/%s - %s\n", color.MagentaString(j.pkg.Release.Name), color.MagentaString(j.pkg.Name), color.MagentaString(dep.Name)) case <-c.signalDependencies[dep.Fingerprint]: c.ui.Printf("depdone: %s/%s - %s\n", color.MagentaString(j.pkg.Release.Name), color.MagentaString(j.pkg.Name), color.MagentaString(dep.Name)) done = true } } } if c.metricsPath != "" { stampy.Stamp(c.metricsPath, "fissile", waitSeriesName, "done") } c.ui.Printf("compile: %s/%s\n", color.MagentaString(j.pkg.Release.Name), color.MagentaString(j.pkg.Name)) // Time spent in actual compilation if c.metricsPath != "" { stampy.Stamp(c.metricsPath, "fissile", runSeriesName, "start") } workerErr := compilePackageHarness(c, j.pkg) if c.metricsPath != "" { stampy.Stamp(c.metricsPath, "fissile", runSeriesName, "done") } c.ui.Printf("done: %s/%s\n", color.MagentaString(j.pkg.Release.Name), color.MagentaString(j.pkg.Name)) j.doneCh <- compileResult{pkg: j.pkg, err: workerErr} }