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

Commit

Permalink
Merge pull request #160 from vania-pooh/master
Browse files Browse the repository at this point in the history
Added ability to specify browser version constraints and download And…
  • Loading branch information
vania-pooh authored May 31, 2018
2 parents b65a806 + b9a3507 commit 071658d
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 76 deletions.
2 changes: 1 addition & 1 deletion docs/selenoid-commands.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ This command does nothing when already downloaded. Use `--force` flag to downloa
+
[source,bash]
----
./cm selenoid configure [--browsers firefox,opera] [--last-versions 2] [--tmpfs 128]
./cm selenoid configure [--browsers firefox:>45.0,opera,android] [--last-versions 2] [--tmpfs 128]
----
+
Use `--browsers` to limit browsers to be configured, `--tmpfs` - to add https://en.wikipedia.org/wiki/Tmpfs[Tmpfs] support, `--last-versions` - to limit how many last browser versions to download. If you wish to download all available versions - specify `--last-versions 0`.
Expand Down
122 changes: 72 additions & 50 deletions selenoid/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import (
const (
Latest = "latest"
firefox = "firefox"
android = "android"
opera = "opera"
tag_1216 = "12.16"
selenoidImage = "aerokube/selenoid"
Expand Down Expand Up @@ -158,15 +159,15 @@ func (c *DockerConfigurator) initAuthConfig() (*types.AuthConfig, error) {
}

func (c *DockerConfigurator) initRegistryClient() error {
url := strings.TrimSuffix(c.RegistryUrl, "/")
u := strings.TrimSuffix(c.RegistryUrl, "/")
username, password := "", ""
if c.authConfig != nil {
username, password = c.authConfig.Username, c.authConfig.Password
}
reg := &registry.Registry{
URL: url,
URL: u,
Client: &http.Client{
Transport: registry.WrapTransport(http.DefaultTransport, url, username, password),
Transport: registry.WrapTransport(http.DefaultTransport, u, username, password),
},
Logf: func(format string, args ...interface{}) {
c.Tracef(format, args...)
Expand Down Expand Up @@ -319,32 +320,21 @@ func (c *DockerConfigurator) Configure() (*SelenoidConfig, error) {
}

func (c *DockerConfigurator) createConfig() SelenoidConfig {
supportedBrowsers := c.getSupportedBrowsers()
requestedBrowsers := c.parseRequestedBrowsers(c.Browsers)
browsersToIterate := c.getBrowsersToIterate(requestedBrowsers)
browsers := make(map[string]config.Versions)
browsersToIterate := supportedBrowsers
if c.Browsers != "" {
requestedBrowsers := strings.Split(c.Browsers, comma)
if len(requestedBrowsers) > 0 {
browsersToIterate = make(map[string]string)
for _, rb := range requestedBrowsers {
if image, ok := supportedBrowsers[rb]; ok {
browsersToIterate[rb] = image
continue
}
c.Errorf("Unsupported browser: %s", rb)
}
}
}
for browserName, image := range browsersToIterate {
c.Titlef(`Processing browser "%v"...`, color.GreenString(browserName))
tags := c.fetchImageTags(image)
image, tags = c.preProcessImageTags(image, browserName, tags)
pulledTags := tags
if c.VNC {
c.Pointf("Requested to download VNC images...")
image = fmt.Sprintf("selenoid/vnc_%s", browserName)
}
versionConstraint := requestedBrowsers[browserName]
pulledTags := c.filterTags(tags, versionConstraint)
fullyQualifiedImage := c.getFullyQualifiedImageRef(image)
if c.DownloadNeeded {
pulledTags = c.pullImages(fullyQualifiedImage, tags)
} else if c.LastVersions > 0 && c.LastVersions <= len(tags) {
pulledTags = tags[:c.LastVersions]
pulledTags = c.pullImages(fullyQualifiedImage, pulledTags)
}

if len(pulledTags) > 0 {
Expand All @@ -357,12 +347,46 @@ func (c *DockerConfigurator) createConfig() SelenoidConfig {
return browsers
}

func (c *DockerConfigurator) getSupportedBrowsers() map[string]string {
return map[string]string{
func (c *DockerConfigurator) parseRequestedBrowsers(requestedBrowsers string) map[string]*ver.Constraints {
ret := make(map[string]*ver.Constraints)
for _, section := range strings.Split(requestedBrowsers, comma) {
pieces := strings.Split(section, colon)
if len(pieces) == 2 {
browserName := pieces[0]
versionConstraintString := pieces[1]
versionConstraint, err := ver.NewConstraint(versionConstraintString)
if err != nil {
c.Errorf("Invalid version constraint %s: %v - ignoring browser %s...", versionConstraintString, err, browserName)
continue
}
ret[browserName] = &versionConstraint
} else if len(pieces) == 1 {
browserName := pieces[0]
ret[browserName] = nil
}
}
return ret
}

func (c *DockerConfigurator) getBrowsersToIterate(requestedBrowsers map[string]*ver.Constraints) map[string]string {
ret := make(map[string]string)
defaultBrowsers := map[string]string{
"firefox": "selenoid/firefox",
"chrome": "selenoid/chrome",
"opera": "selenoid/opera",
}
for browserName := range requestedBrowsers {
if image, ok := defaultBrowsers[browserName]; ok {
ret[browserName] = image
continue
}
c.Errorf("Unsupported browser: %s", browserName)
}

if _, ok := requestedBrowsers[android]; ok {
ret["android"] = "selenoid/android"
}
return ret
}

func (c *DockerConfigurator) fetchImageTags(image string) []string {
Expand All @@ -379,7 +403,7 @@ func (c *DockerConfigurator) fetchImageTags(image string) []string {
}

func filterOutLatest(tags []string) []string {
ret := []string{}
var ret []string
for _, tag := range tags {
if !strings.HasPrefix(tag, Latest) {
ret = append(ret, tag)
Expand All @@ -388,6 +412,26 @@ func filterOutLatest(tags []string) []string {
return ret
}

func (c *DockerConfigurator) filterTags(tags []string, versionConstraint *ver.Constraints) []string {
if versionConstraint != nil {
var ret []string
for _, tag := range tags {
version, err := ver.NewVersion(tag)
if err != nil {
c.Errorf("Skipping tag %s as it does not follow semantic versioning: %v", tag, err)
continue
}
if versionConstraint.Check(version) {
ret = append(ret, tag)
}
}
return ret
} else if c.LastVersions > 0 && c.LastVersions <= len(tags) {
return tags[:c.LastVersions]
}
return tags
}

func (c *DockerConfigurator) createVersions(browserName string, image string, tags []string) config.Versions {
versions := config.Versions{
Default: c.getVersionFromTag(browserName, tags[0]),
Expand All @@ -400,7 +444,7 @@ func (c *DockerConfigurator) createVersions(browserName string, image string, ta
Port: "4444",
Path: "/",
}
if browserName == firefox || (browserName == opera && version == tag_1216) {
if browserName == firefox || browserName == android || (browserName == opera && version == tag_1216) {
browser.Path = "/wd/hub"
}
if c.Tmpfs > 0 {
Expand All @@ -422,18 +466,14 @@ func imageWithTag(image string, tag string) string {
}

func (c *DockerConfigurator) pullImages(image string, tags []string) []string {
pulledTags := []string{}
var pulledTags []string
ctx := context.Background()
loop:
for _, tag := range tags {
ref := imageWithTag(image, tag)
if !c.pullImage(ctx, ref) {
continue
}
pulledTags = append(pulledTags, tag)
if c.LastVersions > 0 && len(pulledTags) == c.LastVersions {
break loop
}
}
return pulledTags
}
Expand All @@ -450,24 +490,6 @@ func (c *DockerConfigurator) getFullyQualifiedImageRef(ref string) string {
return ref
}

func (c *DockerConfigurator) preProcessImageTags(image string, browserName string, tags []string) (string, []string) {
imageToProcess := image
tagsToProcess := tags
if c.VNC {
c.Pointf("Requested to download VNC images...")
imageToProcess = "selenoid/vnc"
tagsToProcess = []string{}
for _, tag := range tags {
tagsToProcess = append(tagsToProcess, createVNCTag(browserName, tag))
}
}
return imageToProcess, tagsToProcess
}

func createVNCTag(browserName string, version string) string {
return fmt.Sprintf("%s_%s", browserName, version)
}

func (c *DockerConfigurator) getVersionFromTag(browserName string, tag string) string {
if c.VNC {
return strings.TrimPrefix(tag, browserName+"_")
Expand Down
28 changes: 3 additions & 25 deletions selenoid/docker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -243,21 +243,6 @@ func TestPullImages(t *testing.T) {
AssertThat(t, tags[1], EqualTo{"45.0"})
}

func TestPreProcessImageTags(t *testing.T) {
image := "selenoid/firefox"
browserName := "firefox"
tags := []string{"33.0", "34.0"}

c, err := NewDockerConfigurator(&LifecycleConfig{
RegistryUrl: mockDockerServer.URL,
VNC: true,
})
AssertThat(t, err, Is{nil})
imageToProcess, tagsToProcess := c.preProcessImageTags(image, browserName, tags)
AssertThat(t, imageToProcess, EqualTo{"selenoid/vnc"})
AssertThat(t, tagsToProcess, EqualTo{[]string{"firefox_33.0", "firefox_34.0"}})
}

func TestConfigureDocker(t *testing.T) {
testConfigure(t, true)
}
Expand All @@ -276,7 +261,7 @@ func testConfigure(t *testing.T, download bool) {
Quiet: false,
LastVersions: 2,
Tmpfs: 512,
Browsers: "firefox,opera",
Browsers: "firefox:>45.0,opera",
Args: "-limit 42",
VNC: true,
Env: testEnv,
Expand All @@ -303,14 +288,7 @@ func testConfigure(t *testing.T, download bool) {

correctFFBrowsers := make(map[string]*config.Browser)
correctFFBrowsers["46.0"] = &config.Browser{
Image: "selenoid/vnc:firefox_46.0",
Port: "4444",
Path: "/wd/hub",
Tmpfs: tmpfsMap,
Env: []string{testEnv},
}
correctFFBrowsers["45.0"] = &config.Browser{
Image: "selenoid/vnc:firefox_45.0",
Image: "selenoid/vnc_firefox:46.0",
Port: "4444",
Path: "/wd/hub",
Tmpfs: tmpfsMap,
Expand All @@ -328,7 +306,7 @@ func testConfigure(t *testing.T, download bool) {

correctOperaBrowsers := make(map[string]*config.Browser)
correctOperaBrowsers["44.0"] = &config.Browser{
Image: "selenoid/vnc:opera_44.0",
Image: "selenoid/vnc_opera:44.0",
Port: "4444",
Path: "/",
Tmpfs: tmpfsMap,
Expand Down
1 change: 1 addition & 0 deletions selenoid/drivers.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ const (
zipMagicHeader = "504b"
gzipMagicHeader = "1f8b"
comma = ","
colon = ":"
owner = "aerokube"
selenoidRepo = "selenoid"
selenoidUIRepo = "selenoid-ui"
Expand Down

0 comments on commit 071658d

Please sign in to comment.