Skip to content
This repository has been archived by the owner on Dec 17, 2024. It is now read-only.

Commit

Permalink
Added ability to print command line args (fixes #144)
Browse files Browse the repository at this point in the history
  • Loading branch information
vania-pooh committed Mar 25, 2018
1 parent df0849f commit c0bf3a8
Show file tree
Hide file tree
Showing 12 changed files with 183 additions and 23 deletions.
12 changes: 12 additions & 0 deletions cmd/selenoid.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ func init() {
initFlags()

selenoidCmd.AddCommand(selenoidDownloadCmd)
selenoidCmd.AddCommand(selenoidArgsCmd)
selenoidCmd.AddCommand(selenoidConfigureCmd)
selenoidCmd.AddCommand(selenoidStartCmd)
selenoidCmd.AddCommand(selenoidStopCmd)
Expand All @@ -40,6 +41,7 @@ func init() {
selenoidCmd.AddCommand(selenoidStatusCmd)

selenoidUICmd.AddCommand(selenoidDownloadUICmd)
selenoidUICmd.AddCommand(selenoidUIArgsCmd)
selenoidUICmd.AddCommand(selenoidStartUICmd)
selenoidUICmd.AddCommand(selenoidStopUICmd)
selenoidUICmd.AddCommand(selenoidUpdateUICmd)
Expand All @@ -50,13 +52,15 @@ func init() {
func initFlags() {
for _, c := range []*cobra.Command{
selenoidDownloadCmd,
selenoidArgsCmd,
selenoidConfigureCmd,
selenoidStartCmd,
selenoidStopCmd,
selenoidUpdateCmd,
selenoidCleanupCmd,
selenoidStatusCmd,
selenoidDownloadUICmd,
selenoidUIArgsCmd,
selenoidStartUICmd,
selenoidStopUICmd,
selenoidUpdateUICmd,
Expand All @@ -67,6 +71,7 @@ func initFlags() {
}
for _, c := range []*cobra.Command{
selenoidDownloadCmd,
selenoidArgsCmd,
selenoidConfigureCmd,
selenoidStartCmd,
selenoidStopCmd,
Expand All @@ -79,6 +84,7 @@ func initFlags() {
}
for _, c := range []*cobra.Command{
selenoidDownloadUICmd,
selenoidUIArgsCmd,
selenoidStartUICmd,
selenoidStopUICmd,
selenoidUpdateUICmd,
Expand All @@ -91,10 +97,12 @@ func initFlags() {

for _, c := range []*cobra.Command{
selenoidDownloadCmd,
selenoidArgsCmd,
selenoidConfigureCmd,
selenoidStartCmd,
selenoidUpdateCmd,
selenoidDownloadUICmd,
selenoidUIArgsCmd,
selenoidStartUICmd,
selenoidUpdateUICmd,
} {
Expand All @@ -103,10 +111,12 @@ func initFlags() {
}
for _, c := range []*cobra.Command{
selenoidDownloadCmd,
selenoidArgsCmd,
selenoidConfigureCmd,
selenoidStartCmd,
selenoidUpdateCmd,
selenoidDownloadUICmd,
selenoidUIArgsCmd,
selenoidStartUICmd,
selenoidUpdateUICmd,
} {
Expand All @@ -128,9 +138,11 @@ func initFlags() {
}
for _, c := range []*cobra.Command{
selenoidDownloadCmd,
selenoidArgsCmd,
selenoidConfigureCmd,
selenoidStartCmd,
selenoidDownloadUICmd,
selenoidUIArgsCmd,
selenoidStartUICmd,
} {
c.Flags().BoolVarP(&force, "force", "f", false, "force action")
Expand Down
32 changes: 32 additions & 0 deletions cmd/selenoid_args.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package cmd

import (
"github.com/aerokube/cm/selenoid"
"github.com/spf13/cobra"
"os"
)

var selenoidArgsCmd = &cobra.Command{
Use: "args",
Short: "Shows Selenoid available args",
Run: func(cmd *cobra.Command, args []string) {
argsImpl(uiConfigDir, uiPort, func(lc *selenoid.Lifecycle) error {
return lc.PrintArgs()
}, force)
},
}

func argsImpl(configDir string, port uint16, argsAction func(*selenoid.Lifecycle) error, force bool) {
lifecycle, err := createLifecycle(configDir, port)
if err != nil {
stderr("Failed to initialize: %v\n", err)
os.Exit(1)
}
lifecycle.Force = force
err = argsAction(lifecycle)
if err != nil {
lifecycle.Errorf("Failed to print args: %v", err)
os.Exit(1)
}
os.Exit(0)
}
16 changes: 16 additions & 0 deletions cmd/selenoid_ui_args.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package cmd

import (
"github.com/aerokube/cm/selenoid"
"github.com/spf13/cobra"
)

var selenoidUIArgsCmd = &cobra.Command{
Use: "args",
Short: "Shows Selenoid UI available args",
Run: func(cmd *cobra.Command, args []string) {
argsImpl(uiConfigDir, uiPort, func(lc *selenoid.Lifecycle) error {
return lc.PrintUIArgs()
}, force)
},
}
1 change: 1 addition & 0 deletions docs/selenoid-commands.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ Supported commands are:
|===
| Command | Meaning

| args | Print Selenoid command line arguments
| cleanup | Removes Selenoid traces
| configure | Creates Selenoid configuration file (implies download)
| download | Downloads Selenoid binary or container image
Expand Down
1 change: 1 addition & 0 deletions docs/selenoid-ui-commands.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Selenoid UI configuration algorithm is similar to Selenoid one - it is started e
|===
| Command | Meaning

| args | Print Selenoid UI command line arguments
| cleanup | Removes Selenoid UI traces
| download | Downloads Selenoid UI binary or container image
| start | Starts Selenoid UI process or container (implies download)
Expand Down
7 changes: 6 additions & 1 deletion selenoid/base.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,16 @@ import (
colorable "github.com/mattn/go-colorable"
)

type StatusAware interface {
type StatusProvider interface {
Status()
UIStatus()
}

type ArgsProvider interface {
PrintArgs() error
PrintUIArgs() error
}

type Downloadable interface {
IsDownloaded() bool
Download() (string, error)
Expand Down
75 changes: 56 additions & 19 deletions selenoid/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import (
"github.com/aerokube/cm/render/rewriter"
dc "github.com/aerokube/util/docker"
"github.com/fatih/color"
"io"
"net/url"
. "vbom.ml/util/sortorder"
)
Expand Down Expand Up @@ -585,6 +586,14 @@ func (c *DockerConfigurator) getContainer(name string, port int) *types.Containe
return nil
}

func (c *DockerConfigurator) PrintArgs() error {
image := c.getSelenoidImage()
if image == nil {
return errors.New("Selenoid image is not downloaded: this is probably a bug")
}
return c.startContainer("", image, 0, 0, []string{}, []string{}, []string{"--help"}, []string{}, true)
}

func (c *DockerConfigurator) Start() error {
image := c.getSelenoidImage()
if image == nil {
Expand Down Expand Up @@ -622,7 +631,7 @@ func (c *DockerConfigurator) Start() error {
if !strings.Contains(c.Env, "OVERRIDE_VIDEO_OUTPUT_DIR") {
overrideEnv = append(overrideEnv, fmt.Sprintf("OVERRIDE_VIDEO_OUTPUT_DIR=%s", videoConfigDir))
}
return c.startContainer(selenoidContainerName, image, c.Port, SelenoidDefaultPort, volumes, []string{}, cmd, overrideEnv)
return c.startContainer(selenoidContainerName, image, c.Port, SelenoidDefaultPort, volumes, []string{}, cmd, overrideEnv, false)
}

func (c *DockerConfigurator) isDockerForWindows() bool {
Expand Down Expand Up @@ -675,6 +684,14 @@ func chooseVolumeConfigDir(defaultConfigDir string, elem []string) string {
return defaultConfigDir
}

func (c *DockerConfigurator) PrintUIArgs() error {
image := c.getSelenoidUIImage()
if image == nil {
return errors.New("Selenoid UI image is not downloaded: this is probably a bug")
}
return c.startContainer("", image, 0, 0, []string{}, []string{}, []string{"--help"}, []string{}, true)
}

func (c *DockerConfigurator) StartUI() error {
image := c.getSelenoidUIImage()
if image == nil {
Expand All @@ -693,7 +710,7 @@ func (c *DockerConfigurator) StartUI() error {
}

overrideEnv := strings.Fields(c.Env)
return c.startContainer(selenoidUIContainerName, image, c.Port, SelenoidUIDefaultPort, []string{}, links, cmd, overrideEnv)
return c.startContainer(selenoidUIContainerName, image, c.Port, SelenoidUIDefaultPort, []string{}, links, cmd, overrideEnv, false)
}

func validateEnviron(envs []string) []string {
Expand All @@ -707,7 +724,7 @@ func validateEnviron(envs []string) []string {
return validEnv
}

func (c *DockerConfigurator) startContainer(name string, image *types.ImageSummary, hostPort int, servicePort int, volumes []string, links []string, cmd []string, envOverride []string) error {
func (c *DockerConfigurator) startContainer(name string, image *types.ImageSummary, hostPort int, servicePort int, volumes []string, links []string, cmd []string, envOverride []string, printLogs bool) error {
ctx := context.Background()
env := validateEnviron(os.Environ())
env = append(env, fmt.Sprintf("TZ=%s", time.Local))
Expand All @@ -717,34 +734,42 @@ func (c *DockerConfigurator) startContainer(name string, image *types.ImageSumma
if !contains(env, dockerApiVersion) {
env = append(env, fmt.Sprintf("%s=%s", dockerApiVersion, c.docker.ClientVersion()))
}
hostPortString := strconv.Itoa(hostPort)
servicePortString := strconv.Itoa(servicePort)
port, err := nat.NewPort("tcp", servicePortString)
if err != nil {
return fmt.Errorf("failed to init port: %v", err)
}
exposedPorts := map[nat.Port]struct{}{port: {}}
portBindings := nat.PortMap{}
portBindings[port] = []nat.PortBinding{{HostIP: "0.0.0.0", HostPort: hostPortString}}
containerConfig := container.Config{
Hostname: "localhost",
Image: image.RepoTags[0],
Env: env,
ExposedPorts: exposedPorts,
Hostname: "localhost",
Image: image.RepoTags[0],
Env: env,
}
if servicePort > 0 {
containerConfig.ExposedPorts = map[nat.Port]struct{}{port: {}}
}
if len(cmd) > 0 {
containerConfig.Cmd = strslice.StrSlice(cmd)
}
hostConfig := container.HostConfig{
Binds: volumes,
Links: links,
}
if printLogs {
containerConfig.Tty = true
} else {
hostConfig.RestartPolicy = container.RestartPolicy{
Name: "always",
}
}
if hostPort > 0 && servicePort > 0 {
hostPortString := strconv.Itoa(hostPort)
portBindings := nat.PortMap{}
portBindings[port] = []nat.PortBinding{{HostIP: "0.0.0.0", HostPort: hostPortString}}
hostConfig.PortBindings = portBindings
}
ctr, err := c.docker.ContainerCreate(ctx,
&containerConfig,
&container.HostConfig{
Binds: volumes,
Links: links,
PortBindings: portBindings,
RestartPolicy: container.RestartPolicy{
Name: "always",
},
},
&hostConfig,
&network.NetworkingConfig{}, name)
if err != nil {
return fmt.Errorf("failed to create container: %v", err)
Expand All @@ -754,6 +779,18 @@ func (c *DockerConfigurator) startContainer(name string, image *types.ImageSumma
c.removeContainer(ctr.ID)
return fmt.Errorf("failed to start container: %v", err)
}
if printLogs {
defer c.removeContainer(ctr.ID)
r, err := c.docker.ContainerLogs(ctx, ctr.ID, types.ContainerLogsOptions{
ShowStdout: true,
ShowStderr: true,
})
if err != nil {
return fmt.Errorf("failed to read container logs: %v", err)
}
defer r.Close()
io.Copy(os.Stderr, r)
}
return nil
}

Expand Down
9 changes: 9 additions & 0 deletions selenoid/docker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,13 @@ func mux() http.Handler {
w.WriteHeader(http.StatusNoContent)
},
))
mux.HandleFunc("/v1.29/containers/e90e34656806/logs", http.HandlerFunc(
func(w http.ResponseWriter, r *http.Request) {
w.Header().Add("Content-Type", "text/plain")
w.WriteHeader(http.StatusOK)
w.Write([]byte("Some logs...\n"))
},
))
mux.HandleFunc("/v1.29/containers/e90e34656806", http.HandlerFunc(
func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNoContent)
Expand Down Expand Up @@ -378,6 +385,7 @@ func TestDownload(t *testing.T) {
ref, err := c.Download()
AssertThat(t, ref, Not{nil})
AssertThat(t, err, Is{nil})
AssertThat(t, c.PrintArgs(), Is{nil})
}

func TestDownloadUI(t *testing.T) {
Expand All @@ -396,6 +404,7 @@ func TestDownloadUI(t *testing.T) {
ref, err := c.DownloadUI()
AssertThat(t, ref, Not{nil})
AssertThat(t, err, Is{nil})
AssertThat(t, c.PrintUIArgs(), Is{nil})
}

func TestGetSelenoidImage(t *testing.T) {
Expand Down
11 changes: 9 additions & 2 deletions selenoid/drivers.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ const (
owner = "aerokube"
selenoidRepo = "selenoid"
selenoidUIRepo = "selenoid-ui"
microsoftEdge = "MicrosoftEdge"
)

type Browsers map[string]Browser
Expand Down Expand Up @@ -567,6 +566,10 @@ func (d *DriversConfigurator) IsUIRunning() bool {
return len(selenoidUIProcesses) > 0
}

func (d *DriversConfigurator) PrintArgs() error {
return runCommand(d.getSelenoidBinaryPath(), []string{"--help"}, []string{})
}

func (d *DriversConfigurator) Start() error {
args := []string{}
overrideArgs := strings.Fields(d.Args)
Expand Down Expand Up @@ -595,6 +598,10 @@ func contains(haystack []string, needle string) bool {
return false
}

func (d *DriversConfigurator) PrintUIArgs() error {
return runCommand(d.getSelenoidUIBinaryPath(), []string{"--help"}, []string{})
}

func (d *DriversConfigurator) StartUI() error {
args := strings.Fields(d.Args)
if !contains(args, "-listen") {
Expand All @@ -604,7 +611,7 @@ func (d *DriversConfigurator) StartUI() error {
return runCommand(d.getSelenoidUIBinaryPath(), args, env)
}

var killFunc func(os.Process) error = func(p os.Process) error {
var killFunc = func(p os.Process) error {
return p.Kill()
}

Expand Down
2 changes: 2 additions & 0 deletions selenoid/drivers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -437,12 +437,14 @@ func TestStartStopProcess(t *testing.T) {
AssertThat(t, configurator.Start(), Is{nil})
configurator.Status()
AssertThat(t, configurator.Stop(), Is{nil})
AssertThat(t, configurator.PrintArgs(), Is{nil})

lcConfig.Port = SelenoidUIDefaultPort
AssertThat(t, configurator.IsUIRunning(), Is{false})
AssertThat(t, configurator.StartUI(), Is{nil})
configurator.UIStatus()
AssertThat(t, configurator.StopUI(), Is{nil})
AssertThat(t, configurator.PrintUIArgs(), Is{nil})
})

}
Expand Down
Loading

0 comments on commit c0bf3a8

Please sign in to comment.