Example #1
0
File: client.go Project: jkary/core
func (c *Client) UploadTools(
	toolsFilename string, vers version.Binary, fakeSeries ...string,
) (
	tools *tools.Tools, err error,
) {
	toolsTarball, err := os.Open(toolsFilename)
	if err != nil {
		return nil, err
	}
	defer toolsTarball.Close()

	// Prepare the upload request.
	url := fmt.Sprintf("%s/tools?binaryVersion=%s&series=%s", c.st.serverRoot, vers, strings.Join(fakeSeries, ","))
	req, err := http.NewRequest("POST", url, toolsTarball)
	if err != nil {
		return nil, fmt.Errorf("cannot create upload request: %v", err)
	}
	req.SetBasicAuth(c.st.tag, c.st.password)
	req.Header.Set("Content-Type", "application/x-tar-gz")

	// Send the request.

	// BUG(dimitern) 2013-12-17 bug #1261780
	// Due to issues with go 1.1.2, fixed later, we cannot use a
	// regular TLS client with the CACert here, because we get "x509:
	// cannot validate certificate for 127.0.0.1 because it doesn't
	// contain any IP SANs". Once we use a later go version, this
	// should be changed to connect to the API server with a regular
	// HTTP+TLS enabled client, using the CACert (possily cached, like
	// the tag and password) passed in api.Open()'s info argument.
	resp, err := utils.GetNonValidatingHTTPClient().Do(req)
	if err != nil {
		return nil, fmt.Errorf("cannot upload charm: %v", err)
	}
	if resp.StatusCode == http.StatusMethodNotAllowed {
		// API server is older than 1.17.5, so tools upload
		// is not supported; notify the client.
		return nil, &params.Error{
			Message: "tools upload is not supported by the API server",
			Code:    params.CodeNotImplemented,
		}
	}

	// Now parse the response & return.
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("cannot read tools upload response: %v", err)
	}
	defer resp.Body.Close()
	var jsonResponse params.ToolsResult
	if err := json.Unmarshal(body, &jsonResponse); err != nil {
		return nil, fmt.Errorf("cannot unmarshal upload response: %v", err)
	}
	if err := jsonResponse.Error; err != nil {
		return nil, fmt.Errorf("error uploading tools: %v", err)
	}
	return jsonResponse.Tools, nil
}
Example #2
0
File: client.go Project: jkary/core
// AddLocalCharm prepares the given charm with a local: schema in its
// URL, and uploads it via the API server, returning the assigned
// charm URL. If the API server does not support charm uploads, an
// error satisfying params.IsCodeNotImplemented() is returned.
func (c *Client) AddLocalCharm(curl *charm.URL, ch charm.Charm) (*charm.URL, error) {
	if curl.Schema != "local" {
		return nil, fmt.Errorf("expected charm URL with local: schema, got %q", curl.String())
	}
	// Package the charm for uploading.
	var archive *os.File
	switch ch := ch.(type) {
	case *charm.Dir:
		var err error
		if archive, err = ioutil.TempFile("", "charm"); err != nil {
			return nil, fmt.Errorf("cannot create temp file: %v", err)
		}
		defer os.Remove(archive.Name())
		defer archive.Close()
		if err := ch.BundleTo(archive); err != nil {
			return nil, fmt.Errorf("cannot repackage charm: %v", err)
		}
		if _, err := archive.Seek(0, 0); err != nil {
			return nil, fmt.Errorf("cannot rewind packaged charm: %v", err)
		}
	case *charm.Bundle:
		var err error
		if archive, err = os.Open(ch.Path); err != nil {
			return nil, fmt.Errorf("cannot read charm archive: %v", err)
		}
		defer archive.Close()
	default:
		return nil, fmt.Errorf("unknown charm type %T", ch)
	}

	// Prepare the upload request.
	url := fmt.Sprintf("%s/charms?series=%s", c.st.serverRoot, curl.Series)
	req, err := http.NewRequest("POST", url, archive)
	if err != nil {
		return nil, fmt.Errorf("cannot create upload request: %v", err)
	}
	req.SetBasicAuth(c.st.tag, c.st.password)
	req.Header.Set("Content-Type", "application/zip")

	// Send the request.

	// BUG(dimitern) 2013-12-17 bug #1261780
	// Due to issues with go 1.1.2, fixed later, we cannot use a
	// regular TLS client with the CACert here, because we get "x509:
	// cannot validate certificate for 127.0.0.1 because it doesn't
	// contain any IP SANs". Once we use a later go version, this
	// should be changed to connect to the API server with a regular
	// HTTP+TLS enabled client, using the CACert (possily cached, like
	// the tag and password) passed in api.Open()'s info argument.
	resp, err := utils.GetNonValidatingHTTPClient().Do(req)
	if err != nil {
		return nil, fmt.Errorf("cannot upload charm: %v", err)
	}
	if resp.StatusCode == http.StatusMethodNotAllowed {
		// API server is 1.16 or older, so charm upload
		// is not supported; notify the client.
		return nil, &params.Error{
			Message: "charm upload is not supported by the API server",
			Code:    params.CodeNotImplemented,
		}
	}

	// Now parse the response & return.
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("cannot read charm upload response: %v", err)
	}
	defer resp.Body.Close()
	var jsonResponse params.CharmsResponse
	if err := json.Unmarshal(body, &jsonResponse); err != nil {
		return nil, fmt.Errorf("cannot unmarshal upload response: %v", err)
	}
	if jsonResponse.Error != "" {
		return nil, fmt.Errorf("error uploading charm: %v", jsonResponse.Error)
	}
	return charm.MustParseURL(jsonResponse.CharmURL), nil
}