// Run is a go routine that performs the deploy job actions. func (d *DeployWorker) Run() { d.wg.Add(1) defer d.wg.Done() // Write the start of job record to the DB. d.db.StartDeploy(d.Opts.Domain, d.Opts.Environment, d.Name, d.Version) // Build standard file name ex: foo.com-development-video-mobile-1.0.1-23.tar.gz tarFilePrefix := fmt.Sprintf("%s-%s-%s-%s", d.Opts.Domain, d.Opts.Environment, d.Name, d.Version) tarFileName := fmt.Sprintf("%s.tar.gz", tarFilePrefix) tarPath := fmt.Sprintf("%s%s/", tmpDir, d.Name) // evaluates as "/tmp/" + "Appname" => "/tmp/Appname/" tarFilePath := fmt.Sprintf("%s%s", tarPath, tarFileName) // evaluates as "/tmp/Appname/" + "foo.tar.gz" => "/tmp/Appname/foo.tar.gz" if err := os.MkdirAll(tarPath, 0744); err != nil { d.log.Errorf("Cannot make tar temp path %s: %s", tarPath, err.Error()) d.db.UpdateDeployByName(d.Opts.Domain, d.Opts.Environment, d.Name, "", cosddb.Failed) return } // Download and untar the assets for this deploy from Artifactory. if errMsg := d.downloadAssets(tarPath, tarFilePath, tarFileName); errMsg != "" { d.log.Errorf(errMsg) d.db.UpdateDeployByName(d.Opts.Domain, d.Opts.Environment, d.Name, "", cosddb.Failed) return } defer os.Remove(tarFilePath) // evaluates as "/tmp/Appname/" + "foo.com-development-video-mobile-1.0.1-23" + "/" untarredPath := fmt.Sprintf("%s%s/", tarPath, tarFilePrefix) defer os.RemoveAll(untarredPath) // Get the filenames from the directory: metaFileName, serviceFileName, etcd2FileName := "", "", "" files, _ := ioutil.ReadDir(untarredPath) for _, f := range files { name := path.Base(f.Name()) switch path.Ext(name) { case ".json": metaFileName = name case ".service": serviceFileName = name case ".tmpl": serviceFileName = name case ".etcd2": etcd2FileName = name default: } } // Validate deploy files exist and set paths. if metaFileName == "" { d.log.Errorf("Metadata file not found in %s", tarFilePath) d.db.UpdateDeployByName(d.Opts.Domain, d.Opts.Environment, d.Name, "", cosddb.Failed) return } if serviceFileName == "" { d.log.Errorf("Service unit file not found in %s", tarFilePath) d.db.UpdateDeployByName(d.Opts.Domain, d.Opts.Environment, d.Name, "", cosddb.Failed) return } metaFilePath := fmt.Sprintf("%s%s", untarredPath, metaFileName) serviceFilePath := fmt.Sprintf("%s%s", untarredPath, serviceFileName) etcd2FilePath := "" if etcd2FileName != "" { etcd2FilePath = fmt.Sprintf("%s%s", untarredPath, etcd2FileName) } // Get the metadata from the file. metaData, errMsg := d.getMetaData(metaFilePath) if errMsg != "" { d.log.Errorf(errMsg) d.db.UpdateDeployByName(d.Opts.Domain, d.Opts.Environment, d.Name, "", cosddb.Failed) return } // Submit a deploy request to the client library. co := &coscl.Options{ Name: metaData.Name, Version: metaData.Version, ImageVersion: metaData.ImageVersion, NumInstances: metaData.NumInstances, TemplateFilePath: serviceFilePath, Etcd2FilePath: etcd2FilePath, Token: d.Opts.DeployToken, Url: d.Opts.DeployURL, Debug: false, } cl := coscl.New(co) // API client deployID, errMsg := d.submitDeployRequest(cl) if errMsg != "" { d.log.Errorf(errMsg) d.db.UpdateDeployByName(d.Opts.Domain, d.Opts.Environment, d.Name, "", cosddb.Failed) return } co.DeployID = deployID d.DeployID = deployID // Loop check the status of the deploy and wait for the deploy to complete. Timeout 1 minute. errMsg = d.submitStatusRequest(cl, deployID) if errMsg != "" { d.log.Errorf(errMsg) d.db.UpdateDeployByName(d.Opts.Domain, d.Opts.Environment, d.Name, deployID, cosddb.Failed) return } // Mark the job complete. d.db.UpdateDeployByName(d.Opts.Domain, d.Opts.Environment, d.Name, d.DeployID, cosddb.Success) }
// main is the main entry point for the client. func main() { opts := &client.Options{} var showVersion bool flag.StringVar(&opts.Name, "n", "", "Name of the service.") flag.StringVar(&opts.Name, "name", "", "Name of the service.") flag.StringVar(&opts.Version, "r", "", "Version of the service.") flag.StringVar(&opts.Version, "service_version", "", "Version of the service.") flag.StringVar(&opts.ImageVersion, "k", "latest", "Version of the docker image.") flag.StringVar(&opts.ImageVersion, "image_version", "latest", "Version of the docker image.") flag.IntVar(&opts.NumInstances, "i", 2, "Number of instances to instantiate.") flag.IntVar(&opts.NumInstances, "instances", 2, "Number of instances to instantiate.") flag.StringVar(&opts.TemplateFilePath, "t", "", "path/file to the unit .service file.") flag.StringVar(&opts.TemplateFilePath, "template_filepath", "", "path/file to the unit .service file.") flag.StringVar(&opts.Etcd2FilePath, "e", "", "path/file to the etcd2 key/value file.") flag.StringVar(&opts.Etcd2FilePath, "etcd2_filepath", "", "path/file to the etcd2 key/value file.") flag.StringVar(&opts.Token, "b", "", "API authorization token") flag.StringVar(&opts.Token, "bearer_token", "", "API authorization token.") flag.StringVar(&opts.Url, "u", "", "URL of the load balancer to the coreos-deploy server.") flag.StringVar(&opts.Url, "url", "", "URL of the load balancer to the coreos-deploy server.") flag.StringVar(&opts.DeployID, "p", "", "Deploy ID to lookup.") flag.StringVar(&opts.DeployID, "deploy_id", "", "Deploy ID to lookup.") flag.BoolVar(&opts.Debug, "d", false, "Enable debugging output.") flag.BoolVar(&opts.Debug, "debug", false, "Enable debugging output.") flag.BoolVar(&showVersion, "V", false, "Show version.") flag.BoolVar(&showVersion, "version", false, "Show version.") flag.Usage = client.PrintUsageAndExit flag.Parse() // Version flag request? if showVersion { client.PrintVersionAndExit() } // Check additional params beyond the flags. for _, arg := range flag.Args() { switch strings.ToLower(arg) { case "version": client.PrintVersionAndExit() case "help": client.PrintUsageAndExit() } } // Validate the mandatory options. if err := opts.Validate(); err != nil { client.PrintErr(err.Error()) return } // Run the deploy. c := client.New(opts) result, err := c.Execute() if err != nil { client.PrintErr(err.Error()) } else { fmt.Println(result) } }