Merge pull request #1856 from databus23/b2d_gh_enterprise_urls

support github enterprise urls for b2d downloads
This commit is contained in:
Olivier Gambier 2015-10-23 10:37:46 -07:00
commit 4e7f8ed7a6
8 changed files with 94 additions and 70 deletions

View File

@ -149,7 +149,7 @@ func (d *Driver) Create() error {
d.setMachineNameIfNotSet()
b2dutils := mcnutils.NewB2dUtils("", "", d.StorePath)
b2dutils := mcnutils.NewB2dUtils(d.StorePath)
if err := b2dutils.CopyIsoToMachineDir(d.boot2DockerURL, d.MachineName); err != nil {
return err
}

View File

@ -223,7 +223,7 @@ func (d *Driver) IsVTXDisabledInTheVM() (bool, error) {
}
func (d *Driver) Create() error {
b2dutils := mcnutils.NewB2dUtils("", "", d.StorePath)
b2dutils := mcnutils.NewB2dUtils(d.StorePath)
if err := b2dutils.CopyIsoToMachineDir(d.Boot2DockerURL, d.MachineName); err != nil {
return err
}

View File

@ -203,7 +203,7 @@ func (d *Driver) PreCreateCheck() error {
}
func (d *Driver) Create() error {
b2dutils := mcnutils.NewB2dUtils("", "", d.StorePath)
b2dutils := mcnutils.NewB2dUtils(d.StorePath)
if err := b2dutils.CopyIsoToMachineDir(d.Boot2DockerURL, d.MachineName); err != nil {
return err
}

View File

@ -226,7 +226,7 @@ func (d *Driver) Create() error {
return err
}
b2dutils := mcnutils.NewB2dUtils("", "", d.StorePath)
b2dutils := mcnutils.NewB2dUtils(d.StorePath)
if err := b2dutils.CopyIsoToMachineDir(d.Boot2DockerURL, d.MachineName); err != nil {
return err
}

View File

@ -10,6 +10,7 @@ import (
"net/url"
"os"
"path/filepath"
"regexp"
"time"
"github.com/docker/machine/libmachine/log"
@ -50,33 +51,19 @@ type B2dUtils struct {
githubBaseUrl string
}
func NewB2dUtils(githubApiBaseUrl, githubBaseUrl, storePath string) *B2dUtils {
defaultBaseApiUrl := "https://api.github.com"
defaultBaseUrl := "https://github.com"
func NewB2dUtils(storePath string) *B2dUtils {
imgCachePath := filepath.Join(storePath, "cache")
isoFilename := "boot2docker.iso"
if githubApiBaseUrl == "" {
githubApiBaseUrl = defaultBaseApiUrl
}
if githubBaseUrl == "" {
githubBaseUrl = defaultBaseUrl
}
return &B2dUtils{
storePath: storePath,
isoFilename: isoFilename,
imgCachePath: imgCachePath,
commonIsoPath: filepath.Join(imgCachePath, isoFilename),
githubApiBaseUrl: githubApiBaseUrl,
githubBaseUrl: githubBaseUrl,
storePath: storePath,
isoFilename: isoFilename,
imgCachePath: imgCachePath,
commonIsoPath: filepath.Join(imgCachePath, isoFilename),
}
}
func (b *B2dUtils) getReleasesRequest() (*http.Request, error) {
apiUrl := fmt.Sprintf("%s/repos/boot2docker/boot2docker/releases", b.githubApiBaseUrl)
func (b *B2dUtils) getReleasesRequest(apiUrl string) (*http.Request, error) {
req, err := http.NewRequest("GET", apiUrl, nil)
if err != nil {
return nil, err
@ -91,33 +78,52 @@ func (b *B2dUtils) getReleasesRequest() (*http.Request, error) {
// Get the latest boot2docker release tag name (e.g. "v0.6.0").
// FIXME: find or create some other way to get the "latest release" of boot2docker since the GitHub API has a pretty low rate limit on API requests
func (b *B2dUtils) GetLatestBoot2DockerReleaseURL() (string, error) {
client := getClient()
func (b *B2dUtils) GetLatestBoot2DockerReleaseURL(apiUrl string) (string, error) {
if apiUrl == "" {
apiUrl = "https://api.github.com/repos/boot2docker/boot2docker/releases"
}
isoUrl := ""
// match github (enterprise) release urls:
// https://api.github.com/repos/../../releases or
// https://some.github.enterprise/api/v3/repos/../../releases
re := regexp.MustCompile("(https?)://([^/]+)(/api/v3)?/repos/([^/]+)/([^/]+)/releases")
if matches := re.FindStringSubmatch(apiUrl); len(matches) == 6 {
scheme := matches[1]
host := matches[2]
org := matches[4]
repo := matches[5]
if host == "api.github.com" {
host = "github.com"
}
client := getClient()
req, err := b.getReleasesRequest(apiUrl)
if err != nil {
return "", err
}
rsp, err := client.Do(req)
if err != nil {
return "", err
}
defer rsp.Body.Close()
req, err := b.getReleasesRequest()
if err != nil {
return "", err
var t []struct {
TagName string `json:"tag_name"`
}
if err := json.NewDecoder(rsp.Body).Decode(&t); err != nil {
return "", fmt.Errorf("Error demarshaling the Github API response: %s\nYou may be getting rate limited by Github.", err)
}
if len(t) == 0 {
return "", fmt.Errorf("no releases found")
}
tag := t[0].TagName
log.Infof("Latest release for %s/%s/%s is %s\n", host, org, repo, tag)
isoUrl = fmt.Sprintf("%s://%s/%s/%s/releases/download/%s/boot2docker.iso", scheme, host, org, repo, tag)
} else {
//does not match a github releases api url
isoUrl = apiUrl
}
rsp, err := client.Do(req)
if err != nil {
return "", err
}
defer rsp.Body.Close()
var t []struct {
TagName string `json:"tag_name"`
}
if err := json.NewDecoder(rsp.Body).Decode(&t); err != nil {
return "", fmt.Errorf("Error demarshaling the Github API response: %s\nYou may be getting rate limited by Github.", err)
}
if len(t) == 0 {
return "", fmt.Errorf("no releases found")
}
tag := t[0].TagName
isoUrl := fmt.Sprintf("%s/boot2docker/boot2docker/releases/download/%s/boot2docker.iso", b.githubBaseUrl, tag)
return isoUrl, nil
}
@ -188,8 +194,8 @@ func (b *B2dUtils) DownloadISO(dir, file, isoUrl string) error {
return nil
}
func (b *B2dUtils) DownloadLatestBoot2Docker() error {
latestReleaseUrl, err := b.GetLatestBoot2DockerReleaseURL()
func (b *B2dUtils) DownloadLatestBoot2Docker(apiUrl string) error {
latestReleaseUrl, err := b.GetLatestBoot2DockerReleaseURL(apiUrl)
if err != nil {
return err
}
@ -227,9 +233,14 @@ func (b *B2dUtils) CopyIsoToMachineDir(isoURL, machineName string) error {
return err
}
} else {
// But if ISO is specified go get it directly
log.Infof("Downloading %s from %s...", b.isoFilename, isoURL)
if err := b.DownloadISO(machineDir, b.isoFilename, isoURL); err != nil {
//if ISO is specified, check if it matches a github releases url or fallback
//to a direct download
if downloadUrl, err := b.GetLatestBoot2DockerReleaseURL(isoURL); err == nil {
log.Infof("Downloading %s from %s...", b.isoFilename, downloadUrl)
if err := b.DownloadISO(machineDir, b.isoFilename, downloadUrl); err != nil {
return err
}
} else {
return err
}
}
@ -240,7 +251,7 @@ func (b *B2dUtils) CopyIsoToMachineDir(isoURL, machineName string) error {
func (b *B2dUtils) copyDefaultIsoToMachine(machineIsoPath string) error {
if _, err := os.Stat(b.commonIsoPath); os.IsNotExist(err) {
log.Info("No default boot2docker iso found locally, downloading the latest release...")
if err := b.DownloadLatestBoot2Docker(); err != nil {
if err := b.DownloadLatestBoot2Docker(""); err != nil {
return err
}
}

View File

@ -16,15 +16,15 @@ func TestGetLatestBoot2DockerReleaseUrl(t *testing.T) {
}))
defer ts.Close()
b := NewB2dUtils(ts.URL, ts.URL, "/tmp/isos")
isoUrl, err := b.GetLatestBoot2DockerReleaseURL()
b := NewB2dUtils("/tmp/isos")
isoUrl, err := b.GetLatestBoot2DockerReleaseURL(ts.URL + "/repos/org/repo/releases")
if err != nil {
t.Fatal(err)
}
expectedUrl := fmt.Sprintf("%s/boot2docker/boot2docker/releases/download/0.1/boot2docker.iso", ts.URL)
expectedUrl := fmt.Sprintf("%s/org/repo/releases/download/0.1/boot2docker.iso", ts.URL)
if isoUrl != expectedUrl {
t.Fatalf("expected url %s; received %s", isoUrl, expectedUrl)
t.Fatalf("expected url %s; received %s", expectedUrl, isoUrl)
}
}
@ -42,7 +42,7 @@ func TestDownloadIso(t *testing.T) {
t.Fatal(err)
}
b := NewB2dUtils(ts.URL, ts.URL, "/tmp/artifacts")
b := NewB2dUtils("/tmp/artifacts")
if err := b.DownloadISO(tmpDir, filename, ts.URL); err != nil {
t.Fatal(err)
}
@ -59,8 +59,8 @@ func TestDownloadIso(t *testing.T) {
func TestGetReleasesRequestNoToken(t *testing.T) {
GithubApiToken = ""
b2d := NewB2dUtils("", "", "/tmp/store")
req, err := b2d.getReleasesRequest()
b2d := NewB2dUtils("/tmp/store")
req, err := b2d.getReleasesRequest("http://some.github.api")
if err != nil {
t.Fatal("Expected err to be nil, got ", err)
}
@ -73,9 +73,9 @@ func TestGetReleasesRequestNoToken(t *testing.T) {
func TestGetReleasesRequest(t *testing.T) {
expectedToken := "CATBUG"
GithubApiToken = expectedToken
b2d := NewB2dUtils("", "", "/tmp/store")
b2d := NewB2dUtils("/tmp/store")
req, err := b2d.getReleasesRequest()
req, err := b2d.getReleasesRequest("http://some.github.api")
if err != nil {
t.Fatal("Expected err to be nil, got ", err)
}

View File

@ -2,6 +2,7 @@ package provision
import (
"bytes"
"encoding/json"
"fmt"
"net"
"path"
@ -70,16 +71,28 @@ func (provisioner *Boot2DockerProvisioner) upgradeIso() error {
// TODO: Ideally, we should not read from mcndirs directory at all.
// The driver should be able to communicate how and where to place the
// relevant files.
b2dutils := mcnutils.NewB2dUtils("", "", mcndirs.GetBaseDir())
b2dutils := mcnutils.NewB2dUtils(mcndirs.GetBaseDir())
// Usually we call this implicitly, but call it here explicitly to get
// the latest boot2docker ISO.
if err := b2dutils.DownloadLatestBoot2Docker(); err != nil {
//Check if the driver has specifed a custom b2d url
jsonDriver, err := json.Marshal(provisioner.GetDriver())
if err != nil {
return err
}
var d struct {
Boot2DockerURL string
}
json.Unmarshal(jsonDriver, &d)
// Copy the latest version of boot2docker ISO to the machine's directory
if err := b2dutils.CopyIsoToMachineDir("", machineName); err != nil {
// Usually we call this implicitly, but call it here explicitly to get
// the latest default boot2docker ISO.
if d.Boot2DockerURL == "" {
if err := b2dutils.DownloadLatestBoot2Docker(d.Boot2DockerURL); err != nil {
return err
}
}
// Either download the latest version of the b2d url that was explicitly
// specified when creating the VM or copy the (updated) default ISO
if err := b2dutils.CopyIsoToMachineDir(d.Boot2DockerURL, machineName); err != nil {
return err
}

View File

@ -180,7 +180,7 @@ func (provisioner *RancherProvisioner) upgradeIso() error {
// TODO: Ideally, we should not read from mcndirs directory at all.
// The driver should be able to communicate how and where to place the
// relevant files.
b2dutils := mcnutils.NewB2dUtils("", "", mcndirs.GetBaseDir())
b2dutils := mcnutils.NewB2dUtils(mcndirs.GetBaseDir())
url, err := provisioner.getLatestISOURL()
if err != nil {