package docker
import (
"fmt"
"io"
"os"
"strings"
"time"
units "github.com/docker/go-units"
docker "github.com/fsouza/go-dockerclient"
"github.com/spf13/cobra"
"github.com/openshift/origin/pkg/bootstrap/docker/dockerhelper"
"github.com/openshift/origin/pkg/bootstrap/docker/errors"
"github.com/openshift/origin/pkg/bootstrap/docker/openshift"
"github.com/openshift/origin/pkg/cmd/server/api"
"github.com/openshift/origin/pkg/cmd/templates"
"github.com/openshift/origin/pkg/cmd/util/clientcmd"
)
// CmdStatusRecommendedName is the recommended command name
const CmdStatusRecommendedName = "status"
var (
cmdStatusLong = templates.LongDesc(`
Show the status of the local OpenShift cluster.
If you started your OpenShift with a specific docker-machine, you need to specify the
same machine using the --docker-machine argument.`)
cmdStatusExample = templates.Examples(`
# See status of local OpenShift cluster
%[1]s
# See status of OpenShift cluster running on Docker machine 'mymachine'
%[1]s --docker-machine=mymachine`)
)
// NewCmdStatus implements the OpenShift cluster status command.
func NewCmdStatus(name, fullName string, f *clientcmd.Factory, out io.Writer) *cobra.Command {
config := &ClientStatusConfig{}
cmd := &cobra.Command{
Use: name,
Short: "Show OpenShift on Docker status",
Long: cmdStatusLong,
Example: fmt.Sprintf(cmdStatusExample, fullName),
Run: func(c *cobra.Command, args []string) {
err := config.Status(f, out)
if err != nil {
PrintError(err, out)
os.Exit(1)
}
},
}
cmd.Flags().StringVar(&config.DockerMachine, "docker-machine", "", "Specify the Docker machine to use")
return cmd
}
// ClientStatusConfig is the configuration for the client status command
type ClientStatusConfig struct {
DockerMachine string
}
// Status prints the OpenShift cluster status
func (c *ClientStatusConfig) Status(f *clientcmd.Factory, out io.Writer) error {
dockerClient, _, err := getDockerClient(out, c.DockerMachine, false)
if err != nil {
return errors.ErrNoDockerClient(err)
}
helper := dockerhelper.NewHelper(dockerClient, nil)
container, running, err := helper.GetContainerState(openshift.OpenShiftContainer)
if err != nil {
return errors.NewError("cannot get state of OpenShift container %s", openshift.OpenShiftContainer).WithCause(err)
}
if !running {
return errors.NewError("OpenShift cluster is not running")
}
healthy, err := isHealthy(f)
if err != nil {
return err
}
if !healthy {
return errors.NewError("OpenShift cluster health check failed")
}
config, err := openshift.GetConfigFromContainer(dockerClient)
if err != nil {
return err
}
fmt.Print(status(container, config))
return nil
}
func isHealthy(f *clientcmd.Factory) (bool, error) {
osClient, _, _, err := f.Clients()
if err != nil {
return false, err
}
var statusCode int
osClient.Client.Timeout = 10 * time.Second
osClient.Get().AbsPath("/healthz").Do().StatusCode(&statusCode)
return statusCode == 200, nil
}
func status(container *docker.Container, config *api.MasterConfig) string {
mountMap := make(map[string]string)
for _, mount := range container.Mounts {
mountMap[mount.Destination] = mount.Source
}
duration := strings.ToLower(units.HumanDuration(time.Now().Sub(container.State.StartedAt)))
status := fmt.Sprintf("The OpenShift cluster was started %s ago\n\n", duration)
status = status + fmt.Sprintf("Web console URL: %s\n", config.AssetConfig.MasterPublicURL)
if config.AssetConfig.MetricsPublicURL != "" {
status = status + fmt.Sprintf("Metrics URL: %s\n", config.AssetConfig.MetricsPublicURL)
}
if config.AssetConfig.LoggingPublicURL != "" {
status = status + fmt.Sprintf("Logging URL: %s\n", config.AssetConfig.LoggingPublicURL)
}
status = status + fmt.Sprintf("\n")
status = status + fmt.Sprintf("Config is at host directory %s\n", mountMap["/var/lib/origin/openshift.local.config"])
status = status + fmt.Sprintf("Volumes are at host directory %s\n", mountMap["/var/lib/origin/openshift.local.volumes"])
if _, hasKey := mountMap["/var/lib/origin/openshift.local.etcd"]; hasKey {
status = status + fmt.Sprintf("Data is at host directory %s\n", mountMap["/var/lib/origin/openshift.local.etcd"])
} else {
status = status + fmt.Sprintf("Data will be discarded when cluster is destroyed\n")
}
return status
}