github.com/ablease/cli@v6.37.1-0.20180613014814-3adbb7d7fb19+incompatible/api/cloudcontroller/ccv3/package.go (about)

     1  package ccv3
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"io"
     7  	"mime/multipart"
     8  	"os"
     9  	"path/filepath"
    10  
    11  	"code.cloudfoundry.org/cli/api/cloudcontroller"
    12  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccerror"
    13  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant"
    14  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal"
    15  )
    16  
    17  // Package represents a Cloud Controller V3 Package.
    18  type Package struct {
    19  	// CreatedAt is the time with zone when the object was created.
    20  	CreatedAt string
    21  
    22  	// DockerImage is the registry address of the docker image.
    23  	DockerImage string
    24  
    25  	// DockerPassword is the password for the docker image's registry.
    26  	DockerPassword string
    27  
    28  	// DockerUsername is the username for the docker image's registry.
    29  	DockerUsername string
    30  
    31  	// GUID is the unique identifier of the package.
    32  	GUID string
    33  
    34  	// Links are links to related resources.
    35  	Links APILinks
    36  
    37  	// Relationships are a list of relationships to other resources.
    38  	Relationships Relationships
    39  
    40  	// State is the state of the package.
    41  	State constant.PackageState
    42  
    43  	// Type is the package type.
    44  	Type constant.PackageType
    45  }
    46  
    47  // MarshalJSON converts a Package into a Cloud Controller Package.
    48  func (p Package) MarshalJSON() ([]byte, error) {
    49  	type ccPackageData struct {
    50  		Image    string `json:"image,omitempty"`
    51  		Username string `json:"username,omitempty"`
    52  		Password string `json:"password,omitempty"`
    53  	}
    54  	var ccPackage struct {
    55  		GUID          string                `json:"guid,omitempty"`
    56  		CreatedAt     string                `json:"created_at,omitempty"`
    57  		Links         APILinks              `json:"links,omitempty"`
    58  		Relationships Relationships         `json:"relationships,omitempty"`
    59  		State         constant.PackageState `json:"state,omitempty"`
    60  		Type          constant.PackageType  `json:"type,omitempty"`
    61  		Data          *ccPackageData        `json:"data,omitempty"`
    62  	}
    63  
    64  	ccPackage.GUID = p.GUID
    65  	ccPackage.CreatedAt = p.CreatedAt
    66  	ccPackage.Links = p.Links
    67  	ccPackage.Relationships = p.Relationships
    68  	ccPackage.State = p.State
    69  	ccPackage.Type = p.Type
    70  	if p.DockerImage != "" {
    71  		ccPackage.Data = &ccPackageData{
    72  			Image:    p.DockerImage,
    73  			Username: p.DockerUsername,
    74  			Password: p.DockerPassword,
    75  		}
    76  	}
    77  
    78  	return json.Marshal(ccPackage)
    79  }
    80  
    81  // UnmarshalJSON helps unmarshal a Cloud Controller Package response.
    82  func (p *Package) UnmarshalJSON(data []byte) error {
    83  	var ccPackage struct {
    84  		GUID          string                `json:"guid,omitempty"`
    85  		CreatedAt     string                `json:"created_at,omitempty"`
    86  		Links         APILinks              `json:"links,omitempty"`
    87  		Relationships Relationships         `json:"relationships,omitempty"`
    88  		State         constant.PackageState `json:"state,omitempty"`
    89  		Type          constant.PackageType  `json:"type,omitempty"`
    90  		Data          struct {
    91  			Image    string `json:"image"`
    92  			Username string `json:"username"`
    93  			Password string `json:"password"`
    94  		} `json:"data"`
    95  	}
    96  	err := cloudcontroller.DecodeJSON(data, &ccPackage)
    97  	if err != nil {
    98  		return err
    99  	}
   100  
   101  	p.GUID = ccPackage.GUID
   102  	p.CreatedAt = ccPackage.CreatedAt
   103  	p.Links = ccPackage.Links
   104  	p.Relationships = ccPackage.Relationships
   105  	p.State = ccPackage.State
   106  	p.Type = ccPackage.Type
   107  	p.DockerImage = ccPackage.Data.Image
   108  	p.DockerUsername = ccPackage.Data.Username
   109  	p.DockerPassword = ccPackage.Data.Password
   110  
   111  	return nil
   112  }
   113  
   114  // CreatePackage creates a package with the given settings, Type and the
   115  // ApplicationRelationship must be set.
   116  func (client *Client) CreatePackage(pkg Package) (Package, Warnings, error) {
   117  	bodyBytes, err := json.Marshal(pkg)
   118  	if err != nil {
   119  		return Package{}, nil, err
   120  	}
   121  
   122  	request, err := client.newHTTPRequest(requestOptions{
   123  		RequestName: internal.PostPackageRequest,
   124  		Body:        bytes.NewReader(bodyBytes),
   125  	})
   126  	if err != nil {
   127  		return Package{}, nil, err
   128  	}
   129  
   130  	var responsePackage Package
   131  	response := cloudcontroller.Response{
   132  		Result: &responsePackage,
   133  	}
   134  	err = client.connection.Make(request, &response)
   135  
   136  	return responsePackage, response.Warnings, err
   137  }
   138  
   139  // GetPackage returns the package with the given GUID.
   140  func (client *Client) GetPackage(packageGUID string) (Package, Warnings, error) {
   141  	request, err := client.newHTTPRequest(requestOptions{
   142  		RequestName: internal.GetPackageRequest,
   143  		URIParams:   internal.Params{"package_guid": packageGUID},
   144  	})
   145  	if err != nil {
   146  		return Package{}, nil, err
   147  	}
   148  
   149  	var responsePackage Package
   150  	response := cloudcontroller.Response{
   151  		Result: &responsePackage,
   152  	}
   153  	err = client.connection.Make(request, &response)
   154  
   155  	return responsePackage, response.Warnings, err
   156  }
   157  
   158  // GetPackages returns the list of packages.
   159  func (client *Client) GetPackages(query ...Query) ([]Package, Warnings, error) {
   160  	request, err := client.newHTTPRequest(requestOptions{
   161  		RequestName: internal.GetPackagesRequest,
   162  		Query:       query,
   163  	})
   164  	if err != nil {
   165  		return nil, nil, err
   166  	}
   167  
   168  	var fullPackagesList []Package
   169  	warnings, err := client.paginate(request, Package{}, func(item interface{}) error {
   170  		if pkg, ok := item.(Package); ok {
   171  			fullPackagesList = append(fullPackagesList, pkg)
   172  		} else {
   173  			return ccerror.UnknownObjectInListError{
   174  				Expected:   Package{},
   175  				Unexpected: item,
   176  			}
   177  		}
   178  		return nil
   179  	})
   180  
   181  	return fullPackagesList, warnings, err
   182  }
   183  
   184  // UploadPackage uploads a file to a given package's Upload resource. Note:
   185  // fileToUpload is read entirely into memory prior to sending data to CC.
   186  func (client *Client) UploadPackage(pkg Package, fileToUpload string) (Package, Warnings, error) {
   187  	link, ok := pkg.Links["upload"]
   188  	if !ok {
   189  		return Package{}, nil, ccerror.UploadLinkNotFoundError{PackageGUID: pkg.GUID}
   190  	}
   191  
   192  	body, contentType, err := client.createUploadStream(fileToUpload, "bits")
   193  	if err != nil {
   194  		return Package{}, nil, err
   195  	}
   196  
   197  	request, err := client.newHTTPRequest(requestOptions{
   198  		URL:    link.HREF,
   199  		Method: link.Method,
   200  		Body:   body,
   201  	})
   202  	if err != nil {
   203  		return Package{}, nil, err
   204  	}
   205  
   206  	request.Header.Set("Content-Type", contentType)
   207  
   208  	var responsePackage Package
   209  	response := cloudcontroller.Response{
   210  		Result: &responsePackage,
   211  	}
   212  	err = client.connection.Make(request, &response)
   213  
   214  	return responsePackage, response.Warnings, err
   215  }
   216  
   217  func (*Client) createUploadStream(path string, paramName string) (io.ReadSeeker, string, error) {
   218  	file, err := os.Open(path)
   219  	if err != nil {
   220  		return nil, "", err
   221  	}
   222  	defer file.Close()
   223  
   224  	body := &bytes.Buffer{}
   225  	writer := multipart.NewWriter(body)
   226  	part, err := writer.CreateFormFile(paramName, filepath.Base(path))
   227  	if err != nil {
   228  		return nil, "", err
   229  	}
   230  	_, err = io.Copy(part, file)
   231  	if err != nil {
   232  		return nil, "", err
   233  	}
   234  
   235  	err = writer.Close()
   236  
   237  	return bytes.NewReader(body.Bytes()), writer.FormDataContentType(), err
   238  }