// serviced service attach { SERVICEID | SERVICENAME | DEPLOYMENTID/...PARENTNAME.../SERVICENAME/INSTANCE } [COMMAND ...]
428258
func (c *ServicedCli) cmdServiceAttach(ctx *cli.Context) error {
	// verify args
	args := ctx.Args()
	if len(args) < 1 {
		if !ctx.Bool("help") {
			fmt.Fprintf(os.Stderr, "Incorrect Usage.\n\n")
		}
		cli.ShowSubcommandHelp(ctx)
		c.exit(1)
		return nil
	}

	// Bash completion
	if args[len(args)-1] == "--generate-bash-completion" {
		// CC-892: The attach command does not require an additional argument after
		// SERVICE_ID. Disable bash completion after SERVICE_ID.
		return c.exit(1)
	}

	svc, instanceID, err := c.searchForService(ctx.Args().First(), ctx.Bool("no-prefix-match"))
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		c.exit(1)
		return err
	}

	if instanceID < 0 {
		instanceID = 0
	}
	command := ""
	argv := []string{}
	if len(args) > 1 {
		command = args[1]
		argv = args[2:]
	}

	if err := c.driver.AttachServiceInstance(svc.ID, instanceID, command, argv); err != nil {
		fmt.Fprintln(os.Stderr, err)
		c.exit(1)
		return err
	}
	return nil
}
437393
func (c *ServicedCli) cmdHostList(ctx *cli.Context) {
	if len(ctx.Args()) > 0 {
		hostID := ctx.Args()[0]
		if host, err := c.driver.GetHostWithAuthInfo(hostID); err != nil {
			fmt.Fprintln(os.Stderr, err)
		} else if host == nil {
			fmt.Fprintln(os.Stderr, "host not found")
		} else if jsonHost, err := json.MarshalIndent(host, " ", "  "); err != nil {
			fmt.Fprintf(os.Stderr, "failed to marshal host: %s", err)
		} else {
			fmt.Println(string(jsonHost))
		}
		return
	}

	hosts, err := c.driver.GetHostsWithAuthInfo()
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		return
	} else if hosts == nil || len(hosts) == 0 {
		fmt.Fprintln(os.Stderr, "no hosts found")
		return
	}

	if ctx.Bool("verbose") {
		if jsonHost, err := json.MarshalIndent(hosts, " ", "  "); err != nil {
			fmt.Fprintf(os.Stderr, "failed to marshal host list: %s", err)
		} else {
			fmt.Println(string(jsonHost))
		}
	} else {
		t := NewTable(ctx.String("show-fields"))
		for _, h := range hosts {
			var usage string
			if stats, err := c.driver.GetHostMemory(h.ID); err != nil {
				usage = "--"
			} else {
				usage = fmt.Sprintf("%s / %s / %s", bytefmt.ByteSize(uint64(stats.Last)), bytefmt.ByteSize(uint64(stats.Max)), bytefmt.ByteSize(uint64(stats.Average)))
			}
			t.AddRow(map[string]interface{}{
				"ID":          h.ID,
				"Auth":        h.Authenticated,
				"Pool":        h.PoolID,
				"Name":        h.Name,
				"Addr":        h.IPAddr,
				"RPCPort":     h.RPCPort,
				"Cores":       h.Cores,
				"RAM":         bytefmt.ByteSize(h.TotalRAM()),
				"Cur/Max/Avg": usage,
				"Network":     h.PrivateNetwork,
				"Release":     h.ServiceD.Release,
			})
		}
		t.Padding = 6
		t.Print()
	}
}
1106151
func (c *ServicedCli) Run(args []string) {
	if err := c.app.Run(args); err != nil {
		fmt.Fprintf(os.Stderr, "%v\n", err)
	}
}
90535
func (c *ServicedCli) printServiceRun(ctx *cli.Context) {
	var output []string

	args := ctx.Args()
	switch len(args) {
	case 0:
		output = c.services()
	case 1:
		output = c.serviceCommands(args[0])
	}
	fmt.Println(strings.Join(output, "\n"))
}
377060
func (c *ServicedCli) cmdServiceConfigList(ctx *cli.Context) {
	args := ctx.Args()
	if len(args) < 1 {
		fmt.Printf("Incorrect Usage.\n\n")
		cli.ShowCommandHelp(ctx, "list")
		c.exit(1)
		return
	}

	svcDetails, _, err := c.searchForService(args[0], ctx.Bool("no-prefix-match"))
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		c.exit(1)
		return
	}

	service, err := c.driver.GetService(svcDetails.ID)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		c.exit(1)
		return
	}

	configs := service.ConfigFiles

	if len(args) < 2 {
		configList := make([]string, 0)

		for filename := range configs {
			configList = append(configList, filename)
		}
		configJson := map[string]([]string){
			"ConfigFiles": configList,
		}
		if configJsonOut, err := json.MarshalIndent(configJson, " ", "  "); err != nil {
			fmt.Fprintln(os.Stderr, err)
			c.exit(1)
			return
		} else {
			fmt.Printf("%s\n\n", configJsonOut)
			return
		}
	} else {
		filename := args[1]
		if _, found := configs[filename]; found {
			fmt.Printf("%s", configs[filename].Content)
		} else {
			fmt.Printf("Config file %s not found.\n", filename)
			c.exit(1)
			return
		}
	}
	return
}
671633
func (c *ServicedCli) cmdServiceListSnapshots(ctx *cli.Context) {
	showTags := ctx.Bool("show-tags")
	if len(ctx.Args()) < 1 {
		fmt.Printf("Incorrect Usage.\n\n")
		cli.ShowCommandHelp(ctx, "list-snapshots")
		c.exit(1)
		return
	}

	svc, _, err := c.searchForService(ctx.Args().First(), ctx.Bool("no-prefix-match"))
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		c.exit(1)
		return
	}

	if snapshots, err := c.driver.GetSnapshotsByServiceID(svc.ID); err != nil {
		fmt.Fprintln(os.Stderr, err)
		c.exit(1)
	} else if snapshots == nil || len(snapshots) == 0 {
		fmt.Fprintln(os.Stderr, "no snapshots found")
	} else {
		if showTags { //print a table of snapshot, description, tag list
			t := NewTable("Snapshot,Description,Tags")
			for _, s := range snapshots {
				//build a comma-delimited list of the tags
				tags := strings.Join(s.Tags, ",")
				snapshotID := s.SnapshotID
				if s.Invalid {
					snapshotID += " [DEPRECATED]"
				}

				//make the row and add it to the table
				row := make(map[string]interface{})
				row["Snapshot"] = snapshotID
				row["Description"] = s.Description
				row["Tags"] = tags
				t.Padding = 6
				t.AddRow(row)
			}
			//print the table
			t.Print()
		} else { //just print a list of snapshots
			for _, s := range snapshots {
				fmt.Println(s)
			}
		}
	}
	return
}
1255464
func (c *ServicedCli) initScript() {
	c.app.Commands = append(c.app.Commands, cli.Command{
		Name:        "script",
		Usage:       "serviced script",
		Description: "",
		Subcommands: []cli.Command{
			{
				Name:        "parse",
				Usage:       "Parse a script",
				Description: "serviced script parse FILE",
				Action:      c.cmdScriptParse,
			},
			{
				Name:        "run",
				Usage:       "Run a script",
				Description: "serviced script run FILE [--service SERVICEID] [-n]",
				Action:      c.cmdScriptRun,
				Flags: []cli.Flag{
					cli.StringFlag{
						Name:  "service",
						Value: "",
						Usage: "Service to run this script against",
					},
					cli.BoolFlag{
						Name:  "no-op, n",
						Usage: "Run through script without modifying system",
					},
				},
			},
		},
	})
}
124347
func ServiceDescriptorFromContext(ctx context.Context) (*ServiceDescriptor, bool) {
	val, ok := ctx.Value(serviceContextKey).(*ServiceDescriptor)
	return val, ok
}
429382
func (cli *NetworkCli) CmdServiceDetach(chain string, args ...string) error {
	cmd := cli.Subcmd(chain, "detach", "CONTAINER SERVICE", "Removes a container from service backend", false)
	cmd.Require(flag.Min, 2)
	err := cmd.ParseFlags(args, true)
	if err != nil {
		return err
	}

	sn, nn := parseServiceName(cmd.Arg(1))
	containerID, err := lookupContainerID(cli, cmd.Arg(0))
	if err != nil {
		return err
	}

	sandboxID, err := lookupSandboxID(cli, containerID)
	if err != nil {
		return err
	}

	serviceID, err := lookupServiceID(cli, nn, sn)
	if err != nil {
		return err
	}

	_, _, err = readBody(cli.call("DELETE", "/services/"+serviceID+"/backend/"+sandboxID, nil, nil))
	if err != nil {
		return err
	}
	return nil
}
647622
func (c *ServicedCli) initSnapshot() {
	c.app.Commands = append(c.app.Commands, cli.Command{
		Name:        "snapshot",
		Usage:       "Administers environment snapshots",
		Description: "",
		Subcommands: []cli.Command{
			{
				Name:         "list",
				Usage:        "Lists all snapshots",
				Description:  "serviced snapshot list [SERVICEID]",
				BashComplete: c.printServicesFirst,
				Action:       c.cmdSnapshotList,
				Flags: []cli.Flag{
					cli.BoolFlag{
						Name:  "show-tags, t",
						Usage: "shows tags associated with each snapshot",
					},
				},
			}, {
				Name:         "add",
				Usage:        "Take a snapshot of an existing service",
				Description:  "serviced snapshot add SERVICEID",
				BashComplete: c.printServicesFirst,
				Action:       c.cmdSnapshotAdd,
				Flags: []cli.Flag{
					cli.StringFlag{
						Name:  "description, d",
						Value: "",
						Usage: "a description of the snapshot",
					},
					cli.StringFlag{
						Name:  "tag, t",
						Value: "",
						Usage: "a unique tag for the snapshot",
					},
				},
			}, {
				Name:         "remove",
				ShortName:    "rm",
				Usage:        "Removes an existing snapshot",
				Description:  "serviced snapshot remove [SNAPSHOTID | SERVICED TAG-NAME]",
				BashComplete: c.printServicesFirst,
				Action:       c.cmdSnapshotRemove,
				Flags: []cli.Flag{
					cli.BoolFlag{
						Name:  "force, f",
						Usage: "required for deleting all snapshots",
					},
				},
			}, {
				Name:        "commit",
				Usage:       "Snapshots and commits a given service instance",
				Description: "serviced snapshot commit DOCKERID",
				Action:      c.cmdSnapshotCommit,
			}, {
				Name:        "rollback",
				Usage:       "Restores the environment to the state of the given snapshot",
				Description: "serviced snapshot rollback SNAPSHOTID",
				Flags: []cli.Flag{
					cli.BoolFlag{
						Name:  "force-restart",
						Usage: "restarts running services during rollback",
					},
				},
				BashComplete: c.printSnapshotsFirst,
				Action:       c.cmdSnapshotRollback,
			}, {
				Name:         "tag",
				Usage:        "Tags an existing snapshot with TAG-NAME",
				Description:  "serviced snapshot tag SNAPSHOTID TAG-NAME",
				BashComplete: c.printSnapshotsFirst,
				Action:       c.cmdSnapshotTag,
			}, {
				Name:         "untag",
				Usage:        "Removes a tag from an existing snapshot",
				Description:  "serviced snapshot untag SERVICEID TAG-NAME",
				BashComplete: c.printServicesFirst,
				Action:       c.cmdSnapshotRemoveTag,
			},
		},
	})
}
1165686
func (cs Set) Service() string {
	domain, target, _ := cs.Split()
	if domain == "services" {
		return target
	}
	return ""
}
628486
func (c *ServicedCli) initHost() {
	c.app.Commands = append(c.app.Commands, cli.Command{
		Name:        "host",
		Usage:       "Administers host data",
		Description: "",
		Subcommands: []cli.Command{
			{
				Name:         "list",
				Usage:        "Lists all hosts",
				Description:  "serviced host list [SERVICEID]",
				BashComplete: c.printHostsFirst,
				Action:       c.cmdHostList,
				Flags: []cli.Flag{
					cli.BoolFlag{
						Name:  "verbose, v",
						Usage: "Show JSON format",
					},
					cli.StringFlag{
						Name:  "show-fields",
						Value: "ID,Auth,Pool,Name,Addr,RPCPort,Cores,RAM,Cur/Max/Avg,Network,Release",
						Usage: "Comma-delimited list describing which fields to display",
					},
				},
			}, {
				Name:         "add",
				Usage:        "Adds a new host",
				Description:  "serviced host add HOST:PORT RESOURCE_POOL",
				BashComplete: c.printHostAdd,
				Action:       c.cmdHostAdd,
				Flags: []cli.Flag{
					cli.StringFlag{
						Name:  "memory",
						Value: "",
						Usage: "Memory to allocate on this host, e.g. 20G, 50%",
					},
					cli.StringFlag{
						Name:  "nat-address",
						Value: "",
						Usage: "The HOST:PORT of the NAT for this delegate",
					},
					cli.StringFlag{
						Name:  "key-file, k",
						Value: "",
						Usage: "Name of the output host key file",
					},
					cli.BoolFlag{
						Name:  "register, r",
						Usage: "Register delegate keys on the host via ssh",
					},
				},
			}, {
				Name:         "add-private",
				ShortName:    "addme",
				Usage:        "Adds a new host and register via common key",
				Description:  "serviced host add HOST:PORT RESOURCE_POOL",
				BashComplete: c.printHostAddPrivate,
				Action:       c.cmdHostAddPrivate,
				Flags: []cli.Flag{
					cli.StringFlag{
						Name:  "memory",
						Value: "",
						Usage: "Memory to allocate on this host, e.g. 20G, 50%",
					},
					cli.StringFlag{
						Name:  "nat-address",
						Value: "",
						Usage: "The HOST:PORT of the NAT for this delegate",
					},
				},
			}, {
				Name:         "remove",
				ShortName:    "rm",
				Usage:        "Removes an existing host",
				Description:  "serviced host remove HOSTID ...",
				BashComplete: c.printHostsAll,
				Action:       c.cmdHostRemove,
			}, {
				Name:        "register",
				Usage:       "Set the authentication keys to use for this host. When KEYSFILE is -, read from stdin.",
				Description: "serviced host register KEYSFILE",
				Action:      c.cmdHostRegister,
			}, {
				Name:         "set-memory",
				Usage:        "Set the memory allocation for a specific host",
				Description:  "serviced host set-memory HOSTID ALLOCATION",
				BashComplete: c.printHostsAll,
				Action:       c.cmdHostSetMemory,
			},
		},
	})
}
195129
func (c *ServicedCli) cmdMetric(ctx *cli.Context) error {
	args := ctx.Args()
	if len(args) < 2 {
		fmt.Println("Insufficient number of arguments")
		return fmt.Errorf("Insufficient number of arguments")
	}
	metricName := args[0]
	metricValue := args[1]
	message, err := c.driver.PostMetric(metricName, metricValue)
	if err != nil {
		return fmt.Errorf("could not post stats: %s", err)
	}
	return fmt.Errorf(message)
}
494792
func (c *ServicedCli) cmdScriptParse(ctx *cli.Context) {
	args := ctx.Args()
	if len(args) != 1 {
		fmt.Fprintf(os.Stderr, "Incorrect Usage.\n\n")
		return
	}
	fileName := args[0]
	config := script.Config{}
	err := c.driver.ScriptParse(fileName, &config)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
	}
	return
}
969769
func (c *ServicedCli) cmdRestore(ctx *cli.Context) {
	args := ctx.Args()
	if len(args) < 1 {
		fmt.Printf("Incorrect Usage.\n\n")
		cli.ShowCommandHelp(ctx, "restore")
		return
	}

	err := c.driver.Restore(args[0])
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
	}
}
82345
func (c *ServicedCli) cmdServiceEndpoints(ctx *cli.Context) {
	nArgs := len(ctx.Args())
	if nArgs < 1 {
		fmt.Printf("Incorrect Usage.\n\n")
		cli.ShowCommandHelp(ctx, "endpoints")
		c.exit(1)
		return
	}

	svc, _, err := c.searchForService(ctx.Args().First(), ctx.Bool("no-prefix-match"))
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		c.exit(1)
		return
	}

	var reportExports, reportImports bool
	if ctx.Bool("all") {
		reportImports = true
		reportExports = true
	} else if ctx.Bool("imports") {
		reportImports = true
		reportExports = false
	} else {
		reportImports = false
		reportExports = true
	}

	if endpoints, err := c.driver.GetEndpoints(svc.ID, reportImports, reportExports, ctx.Bool("verify")); err != nil {
		fmt.Fprintln(os.Stderr, err)
		c.exit(1)
		return
	} else if len(endpoints) == 0 {
		fmt.Fprintf(os.Stderr, "%s - no endpoints defined\n", svc.Name)
		return
	} else {
		hostmap, err := c.driver.GetHostMap()
		if err != nil {
			fmt.Fprintf(os.Stderr, "Unable to get host info, printing host IDs instead of names: %s", err)
			c.exit(1)
		}

		t := NewTable("Name,ServiceID,Endpoint,Purpose,Host,HostIP,HostPort,ContainerID,ContainerIP,ContainerPort")
		t.Padding = 4
		for _, endpoint := range endpoints {
			serviceName := svc.Name
			if svc.Instances > 1 && endpoint.Endpoint.ContainerID != "" {
				serviceName = fmt.Sprintf("%s/%d", serviceName, endpoint.Endpoint.InstanceID)
			}

			host := endpoint.Endpoint.HostID
			hostinfo, ok := hostmap[endpoint.Endpoint.HostID]
			if ok {
				host = hostinfo.Name
			}

			var hostPort string
			if endpoint.Endpoint.HostPort != 0 {
				hostPort = strconv.Itoa(int(endpoint.Endpoint.HostPort))
			}

			t.AddRow(map[string]interface{}{
				"Name":          serviceName,
				"ServiceID":     endpoint.Endpoint.ServiceID,
				"Endpoint":      endpoint.Endpoint.Application,
				"Purpose":       endpoint.Endpoint.Purpose,
				"Host":          host,
				"HostIP":        endpoint.Endpoint.HostIP,
				"HostPort":      hostPort,
				"ContainerID":   fmt.Sprintf("%-12.12s", endpoint.Endpoint.ContainerID),
				"ContainerIP":   endpoint.Endpoint.ContainerIP,
				"ContainerPort": endpoint.Endpoint.ContainerPort,
			})
		}
		t.Print()
	}
	return
}
1150213
func (c *ServicedCli) cmdServiceClone(ctx *cli.Context) {
	args := ctx.Args()
	if len(args) < 1 {
		fmt.Printf("Incorrect Usage.\n\n")
		cli.ShowCommandHelp(ctx, "clone")
		c.exit(1)
		return
	}

	svc, _, err := c.searchForService(ctx.Args().First(), ctx.Bool("no-prefix-match"))
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error searching for service: %s", err)
		c.exit(1)
		return
	}
	serviceID := svc.ID

	if copiedSvc, err := c.driver.CloneService(serviceID, ctx.String("suffix")); err != nil {
		fmt.Fprintf(os.Stderr, "%s: %s\n", serviceID, err)
		c.exit(1)
	} else if copiedSvc == nil {
		fmt.Fprintln(os.Stderr, "received nil service definition")
		c.exit(1)
	} else {
		fmt.Println(copiedSvc.ID)
	}
	return
}