func (u *Upgradeable) operateBox(writer io.Writer) error { u.w = writer fmt.Fprintf(u.w, lb.W(lb.VM_UPGRADING, lb.INFO, fmt.Sprintf("---- operate box (%s)\n", u.B.GetFullName()))) start := time.Now() opsRan, err := upgrade.Run(upgrade.RunArgs{ Name: u.B.GetFullName(), O: u.B.Operations, Writer: writer, Force: false, }) if err != nil { return err } if !opsRan.Successful() { return nil } elapsed := time.Since(start) if err := u.saveData(opsRan, elapsed); err != nil { log.Errorf("WARNING: couldn't save ops data, ops opts: %#v", u) return err } if !u.ShouldRestart { return nil } fmt.Fprintf(u.w, lb.W(lb.VM_UPGRADING, lb.INFO, fmt.Sprintf("---- operate box (%s) OK\n", u.B.GetFullName()))) return Provisioner.Restart(u.B, u.w) }
func run(args RunArgs) (OperationsRan, error) { operationsToRun, err := getOperations(args.O, true) if err != nil { return nil, err } for _, m := range operationsToRun { if m.Optional { continue } if !m.Ran || !args.Force { fmt.Fprintf(args.Writer, lb.W(lb.VM_UPGRADING, lb.INFO, fmt.Sprintf("Running operation (%q)...\n", m.Raw.Type))) err := m.fn(args.Writer) if err != nil { m.Raw.Status = StatusError return nil, err } m.Ran = true m.Raw.Status = StatusUpgraded fmt.Fprintf(args.Writer, lb.W(lb.VM_UPGRADING, lb.INFO, fmt.Sprintf("Ran operation (%s) OK\n", m.Raw.Type))) } else { fmt.Fprintf(args.Writer, lb.W(lb.VM_UPGRADING, lb.INFO, fmt.Sprintf("Skip operation (%s) OK\n", m.Raw.Type))) } } return operationsToRun, nil }
func (ch *ChefRepo) download(force bool) error { if force { _ = os.RemoveAll(ch.tarfile()) } fmt.Fprintf(ch.writer, lb.W(lb.VM_DEPLOY, lb.INFO, fmt.Sprintf(" create tar (%s)\n", ch.tarfile()))) output, err := os.Create(ch.tarfile()) if err != nil { return err } defer output.Close() response, err := http.Get(ch.tar) if err != nil { return err } defer response.Body.Close() fmt.Fprintf(ch.writer, lb.W(lb.VM_DEPLOY, lb.INFO, fmt.Sprintf(" http GET tar (%s) \n", ch.tar))) // Create the progress reader progressR := &ioprogress.Reader{ Reader: response.Body, Size: response.ContentLength, } _, err = io.Copy(output, progressR) if err != nil { return err } fmt.Fprintf(ch.writer, lb.W(lb.VM_DEPLOY, lb.INFO, fmt.Sprintf(" http GET, write tar (%s) OK\n", ch.tar))) return nil }
func (t *Torr) cleanup() error { fmt.Fprintf(t.writer, lb.W(lb.VM_DEPLOY, lb.INFO, fmt.Sprintf(" cleanup tar (%s) OK\n", t.Source))) if _, err := os.Stat(t.Source); err == nil { if err = os.Remove(t.Source); err != nil { return err } } fmt.Fprintf(t.writer, lb.W(lb.VM_DEPLOY, lb.INFO, fmt.Sprintf(" cleanup tar (%s) OK\n", t.Source))) return nil }
//try downloading tar first, if not, do a clone of the chef-repo func (ch *ChefRepo) Download(force bool) error { _ = provision.EventNotify(constants.StatusCookbookDownloading) fmt.Fprintf(ch.writer, lb.W(lb.VM_DEPLOY, lb.INFO, fmt.Sprintf("--- download (%s)\n", ch.repodir()))) if !ch.exists() || !ch.isUptodate() { if err := ch.download(force); err != nil { return scm().Clone(repository.Repo{URL: ch.git}) } } fmt.Fprintf(ch.writer, lb.W(lb.VM_DEPLOY, lb.INFO, fmt.Sprintf("--- download (%s)OK\n", ch.repodir()))) return nil }
func bootUpBox(boot *BootOpts, writer io.Writer) error { if boot.OK() { fmt.Fprintf(writer, lb.W(lb.VM_DEPLOY, lb.INFO, fmt.Sprintf(" boot for box (%s)\n", boot.B.GetFullName()))) if bs, ok := Provisioner.(provision.Deployer); ok { return bs.Bootstrap(boot.B, writer) } } else { fmt.Fprintf(writer, lb.W(lb.VM_DEPLOY, lb.INFO, fmt.Sprintf(" skip boot for box (%s)\n", boot.B.GetFullName()))) } fmt.Fprintf(writer, lb.W(lb.VM_DEPLOY, lb.INFO, fmt.Sprintf(" boot for box (%s) OK\n", boot.B.GetFullName()))) return nil }
func (u *Upgradeable) saveData(opsRan upgrade.OperationsRan, elapsed time.Duration) error { if u.B.Level == provision.BoxSome { fmt.Fprintf(u.w, lb.W(lb.VM_UPGRADING, lb.INFO, fmt.Sprintf(" operate box saving.. (%s)\n", u.B.GetFullName()))) if comp, err := NewComponent(u.B.Id); err != nil { return err } else if err = comp.UpdateOpsRun(opsRan); err != nil { return err } } fmt.Fprintf(u.w, lb.W(lb.VM_UPGRADING, lb.INFO, fmt.Sprintf(" operate box saving (%s) OK\n", u.B.GetFullName()))) return nil }
func (ch *ChefRepo) Torr() error { fmt.Fprintf(ch.writer, lb.W(lb.VM_DEPLOY, lb.INFO, fmt.Sprintf("--- torr (%s)\n", ch.tarfile()))) if !ch.exists() { tr := NewTorr(ch.tarfile()) tr.Base = ch.repodir() tr.writer = ch.writer if err := tr.untar(); err != nil { return err } return tr.cleanup() } fmt.Fprintf(ch.writer, lb.W(lb.VM_DEPLOY, lb.INFO, fmt.Sprintf("--- torr (%s) OK\n", ch.tarfile()))) return nil }
//remove env.sh.save file func cleanup(bi *BindFile) { fmt.Fprintf(bi.LogWriter, lb.W(lb.VM_UPGRADING, lb.INFO, fmt.Sprintf(" set envs cleaning (%s)\n", bi.envSHdot()))) if _, err := os.Stat(bi.envSHdot()); err == nil { if err = os.Remove(bi.envSHdot()); err != nil { return } } }
func (u *Upgradeable) opsBind(writer io.Writer) error { u.w = writer fmt.Fprintf(u.w, lb.W(lb.VM_UPGRADING, lb.INFO, fmt.Sprintf(" ops bind (%s) is kicking\n", u.B.GetFullName()))) actions := []*action.Action{ &setEnvsAction, } pipeline := action.NewPipeline(actions...) args := runOpsPipelineArgs{ box: u.B, writer: u.w, } if err := pipeline.Execute(&args); err != nil { return err } fmt.Fprintf(u.w, lb.W(lb.VM_UPGRADING, lb.INFO, fmt.Sprintf(" ops bind (%s) OK\n", u.B.GetFullName()))) return nil }
func (u *Upgradeable) opsBuild(writer io.Writer) error { u.w = writer fmt.Fprintf(u.w, lb.W(lb.VM_UPGRADING, lb.INFO, fmt.Sprintf(" ops ci (%s) is kicking\n", u.B.GetFullName()))) actions := []*action.Action{ &cloneBox, &buildBox, //buildpack does everthing } pipeline := action.NewPipeline(actions...) args := runOpsPipelineArgs{ box: u.B, writer: u.w, } if err := pipeline.Execute(&args); err != nil { return err } fmt.Fprintf(u.w, lb.W(lb.VM_UPGRADING, lb.INFO, fmt.Sprintf(" ops ci (%s) OK\n", u.B.GetFullName()))) return nil }
func (bi *BindFile) Mutate(newEnvReader io.Reader) (err error) { ei, err := bi.envSHString() if err != nil { return err } backup(bi) ew, err := bi.envSHWriter() if err != nil { return err } reader := bufio.NewReader(strings.NewReader(ei)) writer := bufio.NewWriter(ew) defer func() { if err == nil { err = writer.Flush() } }() fmt.Fprintf(bi.LogWriter, lb.W(lb.VM_UPGRADING, lb.INFO, fmt.Sprintf(" set envs replacing (%s)\n", bi.envSH()))) var replacer func(string) string if replacer, err = mkReplaceFunction(newEnvReader); err != nil { return err } envRx := regexp.MustCompile(`([a-zA-Z0-9_//-]+)=([a-zA-Z0-9_//-]+)`) eof := false for !eof { var line string line, err = reader.ReadString('\n') if err == io.EOF { err = nil eof = true } else if err != nil { return err } line = envRx.ReplaceAllStringFunc(line, replacer) if _, err = writer.WriteString(line); err != nil { return err } } cleanup(bi) return nil }
//remove env.sh, and rename env.sh.save to env.sh func Revert(bi *BindFile) { fmt.Fprintf(bi.LogWriter, lb.W(lb.VM_UPGRADING, lb.INFO, fmt.Sprintf(" set envs reverting (%s)\n", bi.envSHdot()))) if _, err := os.Stat(bi.envSH()); err == nil { if err = os.Remove(bi.envSH()); err != nil { return } } if _, err := os.Stat(bi.envSHdot()); err == nil { if err = os.Rename(bi.envSHdot(), bi.envSH()); err != nil { return } } return }
// Boot runs the boot of the vm. func (u *Upgradeable) Upgrade() error { var outBuffer bytes.Buffer start := time.Now() logWriter := NewLogWriter(u.B) defer logWriter.Close() writer := io.MultiWriter(&outBuffer, &logWriter) if !u.canCycle() { fmt.Fprintf(writer, lb.W(lb.VM_UPGRADING, lb.INFO, fmt.Sprintf(" skip upgrade for box (%s)\n", u.B.GetFullName()))) return nil } err := u.operateBox(writer) elapsed := time.Since(start) saveErr := saveUpgradeData(u, outBuffer.String(), elapsed) if saveErr != nil { log.Errorf("WARNING: couldn't save upgrade data, deploy opts: %#v", u) } if err != nil { return err } return nil }
func (t *Torr) untar() error { fmt.Fprintf(t.writer, lb.W(lb.VM_DEPLOY, lb.INFO, fmt.Sprintf(" untar (%s)\n", t.Source))) file, err := os.Open(t.Source) if err != nil { return err } defer file.Close() var fileReader io.ReadCloser = file // just in case we are reading a tar.gz file, add a filter to handle gzipped file if strings.HasSuffix(t.Source, ".gz") { if fileReader, err = gzip.NewReader(file); err != nil { return err } defer fileReader.Close() } tarBallReader := tar.NewReader(fileReader) // Extracting tarred files for { header, err := tarBallReader.Next() if err != nil { if err == io.EOF { break } return err } filename := filepath.Join(t.Base, header.Name[strings.Index(header.Name, "/")+1:]) switch header.Typeflag { case tar.TypeDir: // handle directory fmt.Fprintf(t.writer, lb.W(lb.VM_DEPLOY, lb.INFO, fmt.Sprintf(" creating directory (%s)\n", filename))) err = os.MkdirAll(filename, os.FileMode(header.Mode)) // or use 0755 if you prefer if err != nil { return err } case tar.TypeReg: // handle normal file fmt.Fprintf(t.writer, lb.W(lb.VM_DEPLOY, lb.INFO, fmt.Sprintf(" writing untarred (%s)\n", filename))) writer, err := os.Create(filename) if err != nil { return err } io.Copy(writer, tarBallReader) err = os.Chmod(filename, os.FileMode(header.Mode)) if err != nil { return err } writer.Close() default: fmt.Fprintf(t.writer, lb.W(lb.VM_DEPLOY, lb.INFO, fmt.Sprintf(" unable to untar type : %c in file (%s)\n", header.Typeflag, filename))) } } fmt.Fprintf(t.writer, lb.W(lb.VM_DEPLOY, lb.INFO, fmt.Sprintf(" untar (%s) OK\n", t.Source))) return nil }
) type runMachineActionsArgs struct { box *provision.Box writer io.Writer machineStatus utils.Status machineState utils.State provisioner *chefsoloProvisioner state string } var updateStatusInScylla = action.Action{ Name: "update-status-scylla", Forward: func(ctx action.FWContext) (action.Result, error) { args := ctx.Params[0].(runMachineActionsArgs) fmt.Fprintf(args.writer, lb.W(args.machineStatus.String(), lb.INFO, fmt.Sprintf(" update status for machine (%s, %s)", args.box.GetFullName(), args.machineStatus.String()))) var mach machine.Machine if ctx.Previous != nil && strings.Compare(reflect.TypeOf(ctx.Previous).Name(), "Machine") == 0 { mach = ctx.Previous.(machine.Machine) } else { mach = machine.Machine{ Id: args.box.Id, CartonId: args.box.CartonId, CartonsId: args.box.CartonsId, Level: args.box.Level, Name: args.box.GetFullName(), SSH: args.box.SSH, Status: args.machineStatus, State: args.machineState, } }
"strings" ) type runOpsPipelineArgs struct { box *provision.Box writer io.Writer } var setEnvsAction = action.Action{ Name: "set-envs", Forward: func(ctx action.FWContext) (action.Result, error) { args, _ := ctx.Params[0].(*runOpsPipelineArgs) if args == nil { return nil, errors.New("invalid arguments for pipeline, expected *runOpsPipelineArgs") } fmt.Fprintf(args.writer, lb.W(lb.VM_UPGRADING, lb.INFO, fmt.Sprintf(" set envs for box (%s) \n", args.box.GetFullName()))) bi := &bind.BindFile{} if len(args.box.Envs) > 0 { bi.Name = "env.sh" bi.BoxName = args.box.GetFullName() bi.LogWriter = args.writer if err := bi.Mutate(strings.NewReader(args.box.Envs.WrapForInitds())); err != nil { return bi, err } } fmt.Fprintf(args.writer, lb.W(lb.VM_UPGRADING, lb.INFO, fmt.Sprintf(" set envs for box (%s) OK\n", args.box.GetFullName()))) return bi, nil }, Backward: func(ctx action.BWContext) {