func stopAction(c *cli.Context) { cfg, err := loadConfig() if err != nil { logger.Fatal(err) } m := client.NewManager(cfg) containers, err := m.Containers() if err != nil { logger.Fatalf("error getting container info: %s", err) } ids := c.Args() if len(ids) == 0 { logger.Fatalf("you must specify at least one id") } for _, cnt := range containers { // this can probably be more efficient for _, i := range ids { if strings.HasPrefix(cnt.ID, i) { if err := m.Stop(cnt); err != nil { logger.Fatalf("error stopping container: %s\n", err) } fmt.Printf("stopped %s\n", cnt.ID[:12]) } } } }
func infoAction(c *cli.Context) { cfg, err := loadConfig(c) if err != nil { logger.Fatal(err) } m := client.NewManager(cfg) info, err := m.Info() if err != nil { logger.Fatalf("error getting cluster info: %s", err) } cpuPercentage := 0.0 memPercentage := 0.0 if info.ReservedCpus > 0.0 && info.Cpus > 0.0 { cpuPercentage = (info.ReservedCpus / info.Cpus) * 100 } if info.ReservedMemory > 0.0 && info.Memory > 0.0 { memPercentage = (info.ReservedMemory / info.Memory) * 100 } w := tabwriter.NewWriter(os.Stdout, 0, 8, 1, '\t', 0) fmt.Fprintf(w, "Controller Version: %s\n", info.Version) fmt.Fprintf(w, "Cpus: %.2f\n", info.Cpus) fmt.Fprintf(w, "Memory: %.2f MB\n", info.Memory) fmt.Fprintf(w, "Containers: %d\n", info.ContainerCount) fmt.Fprintf(w, "Images: %d\n", info.ImageCount) fmt.Fprintf(w, "Engines: %d\n", info.EngineCount) fmt.Fprintf(w, "Reserved Cpus: %.2f%% (%.2f)\n", cpuPercentage, info.ReservedCpus) fmt.Fprintf(w, "Reserved Memory: %.2f%% (%.2f MB)\n", memPercentage, info.ReservedMemory) w.Flush() }
func loginAction(c *cli.Context) { reader := bufio.NewReader(os.Stdin) fmt.Printf("URL: ") ur, err := reader.ReadString('\n') if err != nil { logger.Fatal(err) } fmt.Printf("Username: "******"Password: ") p := gopass.GetPasswd() sUrl := strings.TrimSpace(string(ur[:])) username := strings.TrimSpace(string(u[:])) pass := strings.TrimSpace(string(p[:])) cfg := &client.ShipyardConfig{ Url: sUrl, Username: username, } m := client.NewManager(cfg) token, err := m.Login(username, pass) if err != nil { logger.Fatal(err) } cfg.Token = token.Token if err := saveConfig(cfg); err != nil { logger.Fatal(err) } }
func containersAction(c *cli.Context) { cfg, err := loadConfig() if err != nil { logger.Fatal(err) } m := client.NewManager(cfg) containers, err := m.Containers() if err != nil { logger.Fatalf("error getting containers: %s", err) } if len(containers) == 0 { return } w := tabwriter.NewWriter(os.Stdout, 0, 8, 1, '\t', 0) fmt.Fprintln(w, "ID\tName\tHost\tState\tPorts") for _, c := range containers { portDefs := []string{} for _, port := range c.Ports { p := fmt.Sprintf("%s/%d:%d", port.Proto, port.Port, port.ContainerPort) portDefs = append(portDefs, p) } ports := strings.Join(portDefs, ", ") state := "unknown" switch c.State.Running { case true: state = "running" case false: state = "stopped" } fmt.Fprintf(w, fmt.Sprintf("%s\t%s\t%s\t%v\t%s\n", c.ID[:12], c.Image.Name, c.Engine.ID, state, ports)) } w.Flush() }
func (m *Manager) init() error { var engines []*citadel.Engine if m.config.ShipyardUrl != "" { cfg := &client.ShipyardConfig{ Url: m.config.ShipyardUrl, ServiceKey: m.config.ShipyardServiceKey, } mgr := client.NewManager(cfg) eng, err := mgr.Engines() if err != nil { return err } for _, e := range eng { engines = append(engines, e.Engine) } } else { engines = m.engines } for _, e := range engines { if err := e.Connect(nil); err != nil { return err } logger.Infof("loaded engine: %s", e.ID) } c, err := cluster.New(scheduler.NewResourceManager(), engines...) if err != nil { return err } m.cluster = c // register handler if err := m.cluster.Events(&EventHandler{Manager: m}); err != nil { return err } return nil }
func eventsAction(c *cli.Context) { cfg, err := loadConfig() if err != nil { logger.Fatal(err) } m := client.NewManager(cfg) events, err := m.Events() if err != nil { logger.Fatalf("error getting events: %s", err) } if len(events) == 0 { return } w := tabwriter.NewWriter(os.Stdout, 0, 8, 1, '\t', 0) fmt.Fprintln(w, "Time\tMessage\tEngine\tType\tTags") for _, e := range events { tags := strings.Join(e.Tags, ",") message := e.Message engine := "" if e.Container != nil { cntId := e.Container.ID[:12] message = fmt.Sprintf("container:%s %s", cntId, e.Message) } if e.Engine != nil { engine = e.Engine.ID } fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\n", e.Time.Format(time.RubyDate), message, engine, e.Type, tags) } w.Flush() }
func runAction(c *cli.Context) { cfg, err := loadConfig() if err != nil { logger.Fatal(err) } m := client.NewManager(cfg) if c.String("name") == "" { logger.Fatal("you must specify an image name") } env := parseEnvironmentVariables(c.StringSlice("env")) ports := parsePorts(c.StringSlice("port")) image := &citadel.Image{ Name: c.String("name"), Cpus: c.Float64("cpus"), Memory: c.Float64("memory"), Hostname: c.String("hostname"), Domainname: c.String("domain"), Labels: c.StringSlice("label"), Args: c.StringSlice("arg"), Environment: env, BindPorts: ports, Type: c.String("type"), } containers, err := m.Run(image, c.Int("count"), c.Bool("pull")) if err != nil { logger.Fatalf("error running container: %s\n", err) } for _, c := range containers { fmt.Printf("started %s on %s\n", c.ID[:12], c.Engine.ID) } }
func logsAction(c *cli.Context) { cfg, err := loadConfig() if err != nil { logger.Fatal(err) } m := client.NewManager(cfg) ids := c.Args() if len(ids) == 0 { logger.Fatal("you must specify an id") } id := ids[0] container, err := m.Container(id) stdout := c.Bool("stdout") stderr := c.Bool("stderr") // if output not specified, use both if stdout == false && stderr == false { stdout = true stderr = true } data, err := m.Logs(container, stdout, stderr) if err != nil { logger.Fatalf("error reading logs: %s", err) } buf := new(bytes.Buffer) buf.ReadFrom(data) io.Copy(os.Stdout, buf) }
func webhookKeyCreateAction(c *cli.Context) { cfg, err := loadConfig() if err != nil { logger.Fatal(err) } m := client.NewManager(cfg) key, err := m.NewWebhookKey(c.String("image")) if err != nil { logger.Fatalf("error generating webhook key: %s\n", err) } fmt.Printf("created key: %s\n", key.Key) }
func serviceKeyCreateAction(c *cli.Context) { cfg, err := loadConfig() if err != nil { logger.Fatal(err) } m := client.NewManager(cfg) key, err := m.NewServiceKey(c.String("description")) if err != nil { logger.Fatalf("error generating service key: %s\n", err) } fmt.Printf("created key: %s\n", key.Key) }
func addExtensionAction(c *cli.Context) { cfg, err := loadConfig(c) if err != nil { logger.Fatal(err) } m := client.NewManager(cfg) extUrl := c.String("url") if extUrl == "" { logger.Fatalf("you must specify an extension config url") } env := parseEnvironmentVariables(c.StringSlice("env")) args := c.StringSlice("arg") resp, err := http.Get(extUrl) if err != nil { logger.Fatalf("unable to get extension config: %s", err) } var ext *shipyard.Extension if err := json.NewDecoder(resp.Body).Decode(&ext); err != nil { logger.Fatalf("error parsing extension config: %s", err, err) } fmt.Printf("configuring %s (%s for more info)\n", ext.Name, ext.Url) // check for configuration for _, pe := range ext.Config.PromptEnvironment { fmt.Printf("enter value for container environment variable %s: ", pe) b := bufio.NewReader(os.Stdin) r, _, err := b.ReadLine() if err != nil { logger.Fatalf("unable to parse input: %s", err) } env[pe] = string(r) } for _, pa := range ext.Config.PromptArgs { fmt.Printf("enter value for container argument %s: ", pa) b := bufio.NewReader(os.Stdin) r, _, err := b.ReadLine() if err != nil { logger.Fatalf("unable to parse input: %s", err) } arg := string(r) if pa != "" { arg = fmt.Sprintf("%s=%s", pa, r) } args = append(args, arg) } ext.Config.Environment = env ext.Config.Args = args if err := m.AddExtension(ext); err != nil { logger.Fatalf("error adding extension: %s", err) } fmt.Printf("added extension name=%s version=%s\n", ext.Name, ext.Version) }
func webhookKeyRemoveAction(c *cli.Context) { cfg, err := loadConfig() if err != nil { logger.Fatal(err) } m := client.NewManager(cfg) removeKeys := c.Args() for _, key := range removeKeys { if err := m.RemoveWebhookKey(key); err != nil { logger.Fatalf("error removing webhook key: %s", err) } fmt.Printf("removed %s\n", key) } }
func runAction(c *cli.Context) { cfg, err := loadConfig(c) if err != nil { logger.Fatal(err) } m := client.NewManager(cfg) if c.String("name") == "" { logger.Fatal("you must specify an image name") } vols := c.StringSlice("vol") env := parseEnvironmentVariables(c.StringSlice("env")) ports := parsePorts(c.StringSlice("port")) links := parseContainerLinks(c.StringSlice("link")) policy, maxRetries, err := parseRestartPolicy(c.String("restart")) if err != nil { logger.Fatalf("error parsing restart policy: %s", err) } rp := citadel.RestartPolicy{ Name: policy, MaximumRetryCount: maxRetries, } image := &citadel.Image{ Name: c.String("name"), ContainerName: c.String("container-name"), Cpus: c.Float64("cpus"), Cpuset: c.String("cpuset"), Memory: c.Float64("memory"), Hostname: c.String("hostname"), Domainname: c.String("domain"), NetworkMode: c.String("network"), Labels: c.StringSlice("label"), Args: c.StringSlice("arg"), Environment: env, Links: links, Publish: c.Bool("publish"), Volumes: vols, BindPorts: ports, RestartPolicy: rp, Type: c.String("type"), } containers, err := m.Run(image, c.Int("count"), c.Bool("pull")) if err != nil { logger.Fatalf("error running container: %s\n", err) } for _, c := range containers { fmt.Printf("started %s on %s\n", c.ID[:12], c.Engine.ID) } }
func removeExtensionAction(c *cli.Context) { cfg, err := loadConfig(c) if err != nil { logger.Fatal(err) } m := client.NewManager(cfg) extIds := c.Args() if len(extIds) == 0 { return } for _, id := range extIds { if err := m.RemoveExtension(id); err != nil { logger.Fatalf("error removing extension: %s", err) } } }
func engineInspectAction(c *cli.Context) { cfg, err := loadConfig(c) if err != nil { logger.Fatal(err) } m := client.NewManager(cfg) if len(c.Args()) == 0 { logger.Fatal("you must specify an id") } id := c.Args()[0] eng, err := m.GetEngine(id) if err != nil { logger.Fatalf("error inspecting engine: %s", err) } b, err := json.MarshalIndent(eng, "", " ") fmt.Println(string(b)) }
func serviceKeyRemoveAction(c *cli.Context) { cfg, err := loadConfig() if err != nil { logger.Fatal(err) } m := client.NewManager(cfg) removeKeys := c.Args() for _, key := range removeKeys { k := &shipyard.ServiceKey{ Key: key, } if err := m.RemoveServiceKey(k); err != nil { logger.Fatalf("error removing service key: %s", err) } fmt.Printf("removed %s\n", key) } }
func containerInspectAction(c *cli.Context) { cfg, err := loadConfig() if err != nil { logger.Fatal(err) } m := client.NewManager(cfg) args := c.Args() if len(args) == 0 { logger.Fatalf("you must specify a container id") } containerId := args[0] container, err := m.GetContainer(containerId) if err != nil { logger.Fatalf("error getting container info: %s", err) } b, err := json.MarshalIndent(container, "", " ") fmt.Println(string(b)) }
func changePasswordAction(c *cli.Context) { cfg, err := loadConfig() if err != nil { logger.Fatal(err) } m := client.NewManager(cfg) fmt.Printf("Password: "******"Confirm: ") p2 := gopass.GetPasswd() pass := strings.TrimSpace(string(p1[:])) pass_confirm := strings.TrimSpace(string(p2[:])) if pass != pass_confirm { logger.Fatal("passwords do not match") } if err := m.ChangePassword(pass); err != nil { logger.Fatal(err) } }
func deleteAccountAction(c *cli.Context) { cfg, err := loadConfig(c) if err != nil { logger.Fatal(err) } m := client.NewManager(cfg) accounts := c.Args() if len(accounts) == 0 { return } for _, acct := range accounts { account := &shipyard.Account{ Username: acct, } if err := m.DeleteAccount(account); err != nil { logger.Fatalf("error deleting account: %s", err) } } }
func scaleAction(c *cli.Context) { cfg, err := loadConfig(c) if err != nil { logger.Fatal(err) } m := client.NewManager(cfg) containerId := c.String("id") count := c.Int("count") container, err := m.Container(containerId) if err != nil { logger.Fatalf("error getting container info: %s", err) } if containerId == "" { logger.Fatalf("you must specify a container id") } if err := m.Scale(container, count); err != nil { logger.Fatalf("error scaling container: %s\n", err) } fmt.Printf("scaled %s to %d\n", container.ID[:12], count) }
func accountsAction(c *cli.Context) { cfg, err := loadConfig(c) if err != nil { logger.Fatal(err) } m := client.NewManager(cfg) accounts, err := m.Accounts() if err != nil { logger.Fatalf("error getting accounts: %s", err) } if len(accounts) == 0 { return } w := tabwriter.NewWriter(os.Stdout, 0, 8, 1, '\t', 0) fmt.Fprintln(w, "Username\tRole") for _, u := range accounts { fmt.Fprintf(w, "%s\t%s\n", u.Username, u.Role.Name) } w.Flush() }
func extensionsAction(c *cli.Context) { cfg, err := loadConfig(c) if err != nil { logger.Fatal(err) } m := client.NewManager(cfg) exts, err := m.Extensions() if err != nil { logger.Fatalf("error getting extensions: %s", err) } if len(exts) == 0 { return } w := tabwriter.NewWriter(os.Stdout, 0, 8, 1, '\t', 0) fmt.Fprintln(w, "ID\tName\tVersion\tAuthor\tImage\tUrl\tDescription") for _, e := range exts { fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\t%s\n", e.ID, e.Name, e.Version, e.Author, e.Image, e.Url, e.Description) } w.Flush() }
func webhookKeysListAction(c *cli.Context) { cfg, err := loadConfig() if err != nil { logger.Fatal(err) } m := client.NewManager(cfg) keys, err := m.WebhookKeys() if err != nil { logger.Fatalf("error getting webhook keys: %s", err) return } if len(keys) == 0 { return } w := tabwriter.NewWriter(os.Stdout, 0, 8, 1, '\t', 0) fmt.Fprintln(w, "Image\tKey") for _, k := range keys { fmt.Fprintf(w, "%s\t%s\n", k.Image, k.Key) } w.Flush() }
func serviceKeysListAction(c *cli.Context) { cfg, err := loadConfig() if err != nil { logger.Fatal(err) } m := client.NewManager(cfg) keys, err := m.ServiceKeys() if err != nil { logger.Fatalf("error getting service keys: %s", err) return } if len(keys) == 0 { return } w := tabwriter.NewWriter(os.Stdout, 0, 8, 1, '\t', 0) fmt.Fprintln(w, "Key\tDescription") for _, k := range keys { fmt.Fprintf(w, "%s\t%s\n", k.Key, k.Description) } w.Flush() }
func engineListAction(c *cli.Context) { cfg, err := loadConfig() if err != nil { logger.Fatal(err) } m := client.NewManager(cfg) engines, err := m.Engines() if err != nil { logger.Fatalf("error getting engines: %s", err) return } if len(engines) == 0 { return } w := tabwriter.NewWriter(os.Stdout, 0, 8, 1, '\t', 0) fmt.Fprintln(w, "ID\tCpus\tMemory\tHost\tLabels") for _, e := range engines { labels := strings.Join(e.Engine.Labels, ",") fmt.Fprintf(w, "%s\t%.2f\t%.2f\t%s\t%s\n", e.Engine.ID, e.Engine.Cpus, e.Engine.Memory, e.Engine.Addr, labels) } w.Flush() }
func engineRemoveAction(c *cli.Context) { cfg, err := loadConfig(c) if err != nil { logger.Fatal(err) } m := client.NewManager(cfg) engines, err := m.Engines() if err != nil { logger.Fatalf("error removing engine: %s\n", err) } removeEngines := c.Args() for _, eng := range engines { // this can probably be more efficient for _, i := range removeEngines { if eng.ID == i { if err := m.RemoveEngine(eng); err != nil { logger.Fatalf("error removing engine: %s", err) } fmt.Printf("removed %s\n", eng.Engine.ID) } } } }
func engineListAction(c *cli.Context) { cfg, err := loadConfig(c) if err != nil { logger.Fatal(err) } m := client.NewManager(cfg) engines, err := m.Engines() if err != nil { logger.Fatalf("error getting engines: %s", err) return } if len(engines) == 0 { return } w := tabwriter.NewWriter(os.Stdout, 0, 8, 1, '\t', 0) fmt.Fprintln(w, "ID\tName\tCpus\tMemory\tHost\tLabels\tHealth\tResponse Time (ms)\tDocker Version") for _, e := range engines { labels := strings.Join(e.Engine.Labels, ",") responseTime := responseTimeToString(e.Health.ResponseTime) fmt.Fprintf(w, "%s\t%s\t%.2f\t%.2f\t%s\t%s\t%s\t%s\t%s\n", e.ID, e.Engine.ID, e.Engine.Cpus, e.Engine.Memory, e.Engine.Addr, labels, e.Health.Status, responseTime, e.DockerVersion) } w.Flush() }
func addAccountAction(c *cli.Context) { cfg, err := loadConfig(c) if err != nil { logger.Fatal(err) } m := client.NewManager(cfg) user := c.String("username") pass := c.String("password") if user == "" || pass == "" { logger.Fatalf("you must specify a username and password") } role, err := m.Role(c.String("role")) if err != nil { logger.Fatal(err) } account := &shipyard.Account{ Username: user, Password: pass, Role: role, } if err := m.AddAccount(account); err != nil { logger.Fatalf("error adding account: %s", err) } }
func engineAddAction(c *cli.Context) { cfg, err := loadConfig(c) if err != nil { logger.Fatal(err) } m := client.NewManager(cfg) id := c.String("id") addr := c.String("addr") if id == "" || addr == "" { logger.Fatalf("you must specify an id and address") } engine := &citadel.Engine{ ID: id, Addr: addr, Cpus: c.Float64("cpus"), Memory: c.Float64("memory"), Labels: c.StringSlice("label"), } sslCertPath := c.String("ssl-cert") sslKeyPath := c.String("ssl-key") caCertPath := c.String("ca-cert") var ( sslCertData = []byte{} sslKeyData = []byte{} caCertData = []byte{} sslErr error ) if sslCertPath != "" && sslKeyPath != "" && caCertPath != "" { sslCert, err := os.Open(sslCertPath) if err != nil { logger.Fatalf("unable to open ssl certificate: %s", err) } sslKey, err := os.Open(sslKeyPath) if err != nil { logger.Fatalf("unable to open ssl key: %s", err) } caCert, err := os.Open(caCertPath) if err != nil { logger.Fatalf("unable to open ca certificate: %s", err) } if _, err := sslCert.Stat(); err != nil { logger.Fatalf("ssl cert is not accessible: %s", err) } if _, err := sslKey.Stat(); err != nil { logger.Fatalf("ssl key is not accessible: %s", err) } if _, err := caCert.Stat(); err != nil { logger.Fatalf("ca cert is not accessible: %s", err) } sslCertData, sslErr = ioutil.ReadAll(sslCert) if sslErr != nil { logger.Fatalf("unable to read ssl certificate: %s", sslErr) } sslKeyData, sslErr = ioutil.ReadAll(sslKey) if sslErr != nil { logger.Fatalf("unable to read ssl key: %s", sslErr) } caCertData, sslErr = ioutil.ReadAll(caCert) if sslErr != nil { logger.Fatalf("unable to read ca certificate: %s", sslErr) } } shipyardEngine := &shipyard.Engine{ SSLCertificate: string(sslCertData), SSLKey: string(sslKeyData), CACertificate: string(caCertData), Engine: engine, } if err := m.AddEngine(shipyardEngine); err != nil { logger.Fatalf("error adding engine: %s", err) } }