Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Streamline cluster up output #13636

Merged
merged 1 commit into from
Apr 7, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pkg/bootstrap/docker/join.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ func (c *ClientJoinConfig) Complete(f *osclientcmd.Factory, cmd *cobra.Command)
}

// Create an OpenShift configuration and start a container that uses it.
c.addTask("Joining OpenShift cluster", c.StartOpenShiftNode)
c.addTask(simpleTask("Joining OpenShift cluster", c.StartOpenShiftNode))

return nil
}
Expand Down
20 changes: 14 additions & 6 deletions pkg/bootstrap/docker/openshift/cnetwork.go
Original file line number Diff line number Diff line change
@@ -1,31 +1,39 @@
package openshift

import (
"fmt"
)

const podNetworkTestCmd = `#!/bin/bash
set -e
echo 'Testing connectivity to master API'
for i in {1..40}; do
if curl -s -S -k -m 1 https://172.30.0.1:8443; then
continue
failed=0
for i in {1..40}; do
if curl -s -S -k -m 1 https://${MASTER_IP}:8443; then
failed=0
break
else
failed=1
fi
done
if [[ ! $? -eq 0 ]]; then
if [[ failed -eq 1 ]]; then
exit 1
fi
echo 'Testing connectivity to master DNS server'
for i in {1..40}; do
if curl -s -S -k -m 1 https://kubernetes.default.svc.cluster.local; then
exit 0
fi
sleep 1
done
exit 1
`

// TestContainerNetworking launches a container that will check whether the container
// can communicate with the master API and DNS endpoints.
func (h *Helper) TestContainerNetworking() error {
func (h *Helper) TestContainerNetworking(ip string) error {
_, err := h.runHelper.New().Image(h.image).
DiscardContainer().
Env(fmt.Sprintf("MASTER_IP=%s", ip)).
DNS("172.30.0.1").
Entrypoint("/bin/bash").
Command("-c", podNetworkTestCmd).
Expand Down
1 change: 1 addition & 0 deletions pkg/bootstrap/docker/openshift/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,7 @@ func GetConfigFromContainer(client *docker.Client) (*configapi.MasterConfig, err
func (h *Helper) serverVersion() (semver.Version, error) {
versionText, _, _, err := h.runHelper.New().Image(h.image).
Command("version").
DiscardContainer().
Output()
if err != nil {
return semver.Version{}, err
Expand Down
159 changes: 100 additions & 59 deletions pkg/bootstrap/docker/up.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,15 @@ type task struct {
name string
fn taskFunc
condition conditionFunc
stdOut bool // true if task's output should go directly to stdout
}

func simpleTask(name string, fn taskFunc) task {
return task{name: name, fn: fn}
}

func conditionalTask(name string, fn taskFunc, condition conditionFunc) task {
return task{name: name, fn: fn, condition: condition}
}

type CommonStartConfig struct {
Expand All @@ -175,9 +184,8 @@ type CommonStartConfig struct {
ShouldInstallLogging bool
PortForwarding bool

Out io.Writer
TaskPrinter *TaskPrinter
Tasks []task
Out io.Writer
Tasks []task

HostName string
LocalConfigDir string
Expand Down Expand Up @@ -219,12 +227,8 @@ type CommonStartConfig struct {
containerNetworkErr chan error
}

func (c *CommonStartConfig) addTask(name string, fn taskFunc) {
c.addConditionalTask(name, fn, nil)
}

func (c *CommonStartConfig) addConditionalTask(name string, fn taskFunc, condition conditionFunc) {
c.Tasks = append(c.Tasks, task{name: name, fn: fn, condition: condition})
func (c *CommonStartConfig) addTask(t task) {
c.Tasks = append(c.Tasks, t)
}

func (config *CommonStartConfig) Bind(flags *pflag.FlagSet) {
Expand Down Expand Up @@ -261,18 +265,19 @@ func (c *CommonStartConfig) Validate(out io.Writer) error {

// Start runs the start tasks ensuring that they are executed in sequence
func (c *CommonStartConfig) Start(out io.Writer) error {
taskPrinter := NewTaskPrinter(out)
for _, task := range c.Tasks {
if task.condition != nil && !task.condition() {
continue
}
c.TaskPrinter.StartTask(task.name)
w := c.TaskPrinter.TaskWriter()
taskPrinter.StartTask(task.name)
w := taskPrinter.TaskWriter()
err := task.fn(w)
if err != nil {
c.TaskPrinter.Failure(err)
taskPrinter.Failure(err)
return err
}
c.TaskPrinter.Success()
taskPrinter.Success()
}
return nil
}
Expand All @@ -287,50 +292,51 @@ func (config *ClientStartConfig) Bind(flags *pflag.FlagSet) {
}

func (c *CommonStartConfig) Complete(f *osclientcmd.Factory, cmd *cobra.Command) error {
c.TaskPrinter = NewTaskPrinter(c.Out)
c.originalFactory = f
c.command = cmd

if len(c.ImageVersion) == 0 {
c.ImageVersion = defaultImageVersion()
}

c.addTask("Checking OpenShift client", c.CheckOpenShiftClient)
c.addTask(simpleTask("Checking OpenShift client", c.CheckOpenShiftClient))

c.addConditionalTask("Create Docker machine", c.CreateDockerMachine, func() bool { return c.ShouldCreateDockerMachine })
c.addTask(conditionalTask("Create Docker machine", c.CreateDockerMachine, func() bool { return c.ShouldCreateDockerMachine }))
// Get a Docker client.
// If a Docker machine was specified, make sure that the machine is
// running. Otherwise, use environment variables.
c.addTask("Checking Docker client", c.GetDockerClient)
c.addTask(simpleTask("Checking Docker client", c.GetDockerClient))

// Check that we have the minimum Docker version available to run OpenShift
c.addTask("Checking Docker version", c.CheckDockerVersion)
c.addTask(simpleTask("Checking Docker version", c.CheckDockerVersion))

// Check for an OpenShift container. If one exists and is running, exit.
// If one exists but not running, delete it.
c.addTask("Checking for existing OpenShift container", c.CheckExistingOpenShiftContainer)
c.addTask(simpleTask("Checking for existing OpenShift container", c.CheckExistingOpenShiftContainer))

// Ensure that the OpenShift Docker image is available. If not present,
// pull it.
c.addTask(fmt.Sprintf("Checking for %s image", c.openshiftImage()), c.CheckOpenShiftImage)
t := simpleTask(fmt.Sprintf("Checking for %s image", c.openshiftImage()), c.CheckOpenShiftImage)
t.stdOut = true
c.addTask(t)

// Ensure that the Docker daemon has the right --insecure-registry argument. If
// not, then exit.
if !c.SkipRegistryCheck {
c.addTask("Checking Docker daemon configuration", c.CheckDockerInsecureRegistry)
c.addTask(simpleTask("Checking Docker daemon configuration", c.CheckDockerInsecureRegistry))
}

// Ensure that ports used by OpenShift are available on the host machine
c.addTask("Checking for available ports", c.CheckAvailablePorts)
c.addTask(simpleTask("Checking for available ports", c.CheckAvailablePorts))

// Check whether the Docker host has the right binaries to use Kubernetes' nsenter mounter
// If not, use a shared volume to mount volumes on OpenShift
c.addTask("Checking type of volume mount", c.CheckNsenterMounter)
c.addTask(simpleTask("Checking type of volume mount", c.CheckNsenterMounter))

// Ensure that host directories exist.
// If not using the nsenter mounter, create a volume share on the host machine to
// mount OpenShift volumes.
c.addTask("Creating host directories", c.EnsureHostDirectories)
c.addTask(simpleTask("Creating host directories", c.EnsureHostDirectories))

// Determine an IP to use for OpenShift.
// The result is that c.ServerIP will be populated with
Expand All @@ -348,7 +354,7 @@ func (c *CommonStartConfig) Complete(f *osclientcmd.Factory, cmd *cobra.Command)
// included in the server's certificate. These include any IPs that are currently
// assigned to the Docker host (hostname -I)
// Each IP is tested to ensure that it can be accessed from the current client
c.addTask("Finding server IP", c.DetermineServerIP)
c.addTask(simpleTask("Finding server IP", c.DetermineServerIP))

return nil
}
Expand All @@ -360,47 +366,49 @@ func (c *ClientStartConfig) Complete(f *osclientcmd.Factory, cmd *cobra.Command)
}

// Create an OpenShift configuration and start a container that uses it.
c.addTask("Starting OpenShift container", c.StartOpenShift)
c.addTask(simpleTask("Starting OpenShift container", c.StartOpenShift))

// Add default redirect URIs to an OAuthClient to enable local web-console development.
c.addConditionalTask("Adding default OAuthClient redirect URIs", c.EnsureDefaultRedirectURIs, c.ShouldInitializeData)
c.addTask(conditionalTask("Adding default OAuthClient redirect URIs", c.EnsureDefaultRedirectURIs, c.ShouldInitializeData))

// Install a registry
c.addConditionalTask("Installing registry", c.InstallRegistry, c.ShouldInitializeData)
c.addTask(conditionalTask("Installing registry", c.InstallRegistry, c.ShouldInitializeData))

// Install a router
c.addConditionalTask("Installing router", c.InstallRouter, c.ShouldInitializeData)
c.addTask(conditionalTask("Installing router", c.InstallRouter, c.ShouldInitializeData))

// Install metrics
c.addConditionalTask("Installing metrics", c.InstallMetrics, func() bool {
c.addTask(conditionalTask("Installing metrics", c.InstallMetrics, func() bool {
return c.ShouldInstallMetrics && c.ShouldInitializeData()
})
}))

// Import default image streams
c.addConditionalTask("Importing image streams", c.ImportImageStreams, c.ShouldInitializeData)
c.addTask(conditionalTask("Importing image streams", c.ImportImageStreams, c.ShouldInitializeData))

// Import templates
c.addConditionalTask("Importing templates", c.ImportTemplates, c.ShouldInitializeData)
c.addTask(conditionalTask("Importing templates", c.ImportTemplates, c.ShouldInitializeData))

// Install logging
c.addConditionalTask("Installing logging", c.InstallLogging, func() bool {
c.addTask(conditionalTask("Installing logging", c.InstallLogging, func() bool {
return c.ShouldInstallLogging && c.ShouldInitializeData()
})
}))

// Login with an initial default user
c.addConditionalTask("Login to server", c.Login, c.ShouldCreateUser)
c.addTask(conditionalTask("Login to server", c.Login, c.ShouldCreateUser))

// Create an initial project
c.addConditionalTask(fmt.Sprintf("Creating initial project %q", initialProjectName), c.CreateProject, c.ShouldCreateUser)
c.addTask(conditionalTask(fmt.Sprintf("Creating initial project %q", initialProjectName), c.CreateProject, c.ShouldCreateUser))

// Remove temporary directory
c.addTask("Removing temporary directory", c.RemoveTemporaryDirectory)
c.addTask(simpleTask("Removing temporary directory", c.RemoveTemporaryDirectory))

// Check container networking
c.addTask("Checking container networking", c.CheckContainerNetworking)
// Check container networking (only when loglevel > 0)
if glog.V(1) {
c.addTask(simpleTask("Checking container networking", c.CheckContainerNetworking))
}

// Display server information
c.addTask("Server Information", c.ServerInfo)
c.addTask(simpleTask("Server Information", c.ServerInfo))

return nil
}
Expand All @@ -416,18 +424,44 @@ func (c *ClientStartConfig) Validate(out, errout io.Writer) error {

// Start runs the start tasks ensuring that they are executed in sequence
func (c *ClientStartConfig) Start(out io.Writer) error {
for _, task := range c.Tasks {
if task.condition != nil && !task.condition() {
continue
var detailedOut io.Writer

// When loglevel > 0, just use stdout to write all messages
if glog.V(1) {
detailedOut = out
} else {
fmt.Fprintf(out, "Starting OpenShift using %s ...\n", c.openshiftImage())
detailedOut = &bytes.Buffer{}
}

taskPrinter := NewTaskPrinter(detailedOut)
startError := func() error {
for _, task := range c.Tasks {
if task.condition != nil && !task.condition() {
continue
}
taskPrinter.StartTask(task.name)
w := taskPrinter.TaskWriter()
if task.stdOut && !bool(glog.V(1)) {
w = io.MultiWriter(w, out)
}
err := task.fn(w)
if err != nil {
taskPrinter.Failure(err)
return err
}
taskPrinter.Success()
}
c.TaskPrinter.StartTask(task.name)
w := c.TaskPrinter.TaskWriter()
err := task.fn(w)
if err != nil {
c.TaskPrinter.Failure(err)
return err
return nil
}()
if startError != nil {
if !bool(glog.V(1)) {
fmt.Fprintf(out, "%s", detailedOut.(*bytes.Buffer).String())
}
c.TaskPrinter.Success()
return startError
}
if !bool(glog.V(1)) {
c.ServerInfo(out)
}
return nil
}
Expand Down Expand Up @@ -790,10 +824,15 @@ func (c *ClientStartConfig) StartOpenShift(out io.Writer) error {
return err
}

serverIP, err := c.OpenShiftHelper().ServerIP()
if err != nil {
return err
}

// Start a container networking test
c.containerNetworkErr = make(chan error)
go func() {
c.containerNetworkErr <- c.OpenShiftHelper().TestContainerNetworking()
c.containerNetworkErr <- c.OpenShiftHelper().TestContainerNetworking(serverIP)
}()

// Setup persistent storage
Expand All @@ -816,13 +855,17 @@ func (c *ClientStartConfig) StartOpenShift(out io.Writer) error {
}

func (c *ClientStartConfig) CheckContainerNetworking(out io.Writer) error {
serverIP, err := c.OpenShiftHelper().ServerIP()
if err != nil {
return err
}
networkErr := <-c.containerNetworkErr
if networkErr != nil {
return errors.NewError("containers cannot communicate with the OpenShift master").
WithDetails("The cluster was started. However, the container networking test failed.").
WithSolution(
fmt.Sprintf("Ensure that access to ports tcp/8443, udp/53 and udp/8053 is allowed on %s.\n"+
"You may need to open these ports on your machine's firewall.", c.ServerIP)).
"You may need to open these ports on your machine's firewall.", serverIP)).
WithCause(networkErr)
}
return nil
Expand Down Expand Up @@ -934,19 +977,17 @@ func (c *ClientStartConfig) ServerInfo(out io.Writer) error {
if len(c.PublicHostname) > 0 {
masterURL = fmt.Sprintf("https://%s:8443", c.PublicHostname)
}
msg := fmt.Sprintf("OpenShift server started.\n"+
msg := fmt.Sprintf("OpenShift server started.\n\n"+
"The server is accessible via web console at:\n"+
" %s\n\n%s%s", masterURL, metricsInfo, loggingInfo)

if c.ShouldCreateUser() {
msg += fmt.Sprintf("You are logged in as:\n"+
" User: %s\n"+
" Password: %s\n\n", initialUser, initialPassword)
" User: %s\n\n", initialUser)
msg += "To login as administrator:\n" +
" oc login -u system:admin\n\n"
}

msg += "To login as administrator:\n" +
" oc login -u system:admin\n\n"

msg += c.checkProxySettings()

fmt.Fprintf(out, msg)
Expand Down