github.com/franc20/ayesa_sap@v7.0.0-beta.28.0.20200124003224-302d4d52fa6c+incompatible/api/cloudcontroller/ccv2/buildpack.go (about) 1 package ccv2 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "io" 7 8 "code.cloudfoundry.org/cli/api/cloudcontroller" 9 "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" 10 "code.cloudfoundry.org/cli/api/cloudcontroller/ccv2/internal" 11 "code.cloudfoundry.org/cli/api/cloudcontroller/uploads" 12 "code.cloudfoundry.org/cli/types" 13 ) 14 15 // Buildpack represents a Cloud Controller Buildpack. 16 type Buildpack struct { 17 Locked types.NullBool 18 Enabled types.NullBool 19 GUID string 20 Name string 21 Position types.NullInt 22 Stack string 23 } 24 25 func (buildpack Buildpack) MarshalJSON() ([]byte, error) { 26 ccBuildpack := struct { 27 Locked *bool `json:"locked,omitempty"` 28 Enabled *bool `json:"enabled,omitempty"` 29 Name string `json:"name"` 30 Position *int `json:"position,omitempty"` 31 Stack string `json:"stack,omitempty"` 32 }{ 33 Name: buildpack.Name, 34 Stack: buildpack.Stack, 35 } 36 37 if buildpack.Position.IsSet { 38 ccBuildpack.Position = &buildpack.Position.Value 39 } 40 if buildpack.Enabled.IsSet { 41 ccBuildpack.Enabled = &buildpack.Enabled.Value 42 } 43 if buildpack.Locked.IsSet { 44 ccBuildpack.Locked = &buildpack.Locked.Value 45 } 46 47 return json.Marshal(ccBuildpack) 48 } 49 50 func (buildpack *Buildpack) UnmarshalJSON(data []byte) error { 51 var alias struct { 52 Metadata internal.Metadata `json:"metadata"` 53 Entity struct { 54 Locked types.NullBool `json:"locked"` 55 Enabled types.NullBool `json:"enabled"` 56 Name string `json:"name"` 57 Position types.NullInt `json:"position"` 58 Stack string `json:"stack"` 59 } `json:"entity"` 60 } 61 62 err := json.Unmarshal(data, &alias) 63 if err != nil { 64 return err 65 } 66 67 buildpack.Locked = alias.Entity.Locked 68 buildpack.Enabled = alias.Entity.Enabled 69 buildpack.GUID = alias.Metadata.GUID 70 buildpack.Name = alias.Entity.Name 71 buildpack.Position = alias.Entity.Position 72 buildpack.Stack = alias.Entity.Stack 73 return nil 74 } 75 76 // CreateBuildpack creates a new buildpack. 77 func (client *Client) CreateBuildpack(buildpack Buildpack) (Buildpack, Warnings, error) { 78 body, err := json.Marshal(buildpack) 79 if err != nil { 80 return Buildpack{}, nil, err 81 } 82 83 request, err := client.newHTTPRequest(requestOptions{ 84 RequestName: internal.PostBuildpackRequest, 85 Body: bytes.NewReader(body), 86 }) 87 if err != nil { 88 return Buildpack{}, nil, err 89 } 90 91 var createdBuildpack Buildpack 92 response := cloudcontroller.Response{ 93 DecodeJSONResponseInto: &createdBuildpack, 94 } 95 96 err = client.connection.Make(request, &response) 97 return createdBuildpack, response.Warnings, err 98 } 99 100 // GetBuildpacks searches for a buildpack with the given name and returns it if it exists. 101 func (client *Client) GetBuildpacks(filters ...Filter) ([]Buildpack, Warnings, error) { 102 request, err := client.newHTTPRequest(requestOptions{ 103 RequestName: internal.GetBuildpacksRequest, 104 Query: ConvertFilterParameters(filters), 105 }) 106 107 if err != nil { 108 return nil, nil, err 109 } 110 111 var buildpacks []Buildpack 112 warnings, err := client.paginate(request, Buildpack{}, func(item interface{}) error { 113 if buildpack, ok := item.(Buildpack); ok { 114 buildpacks = append(buildpacks, buildpack) 115 } else { 116 return ccerror.UnknownObjectInListError{ 117 Expected: Buildpack{}, 118 Unexpected: item, 119 } 120 } 121 return nil 122 }) 123 124 return buildpacks, warnings, err 125 } 126 127 // UpdateBuildpack updates the buildpack with the provided GUID and returns the 128 // updated buildpack. Note: Stack cannot be updated without uploading a new 129 // buildpack. 130 func (client *Client) UpdateBuildpack(buildpack Buildpack) (Buildpack, Warnings, error) { 131 body, err := json.Marshal(buildpack) 132 if err != nil { 133 return Buildpack{}, nil, err 134 } 135 136 request, err := client.newHTTPRequest(requestOptions{ 137 RequestName: internal.PutBuildpackRequest, 138 URIParams: Params{"buildpack_guid": buildpack.GUID}, 139 Body: bytes.NewReader(body), 140 }) 141 if err != nil { 142 return Buildpack{}, nil, err 143 } 144 145 var updatedBuildpack Buildpack 146 response := cloudcontroller.Response{ 147 DecodeJSONResponseInto: &updatedBuildpack, 148 } 149 150 err = client.connection.Make(request, &response) 151 if err != nil { 152 return Buildpack{}, response.Warnings, err 153 } 154 155 return updatedBuildpack, response.Warnings, nil 156 } 157 158 // UploadBuildpack uploads the contents of a buildpack zip to the server. 159 func (client *Client) UploadBuildpack(buildpackGUID string, buildpackPath string, buildpack io.Reader, buildpackLength int64) (Warnings, error) { 160 161 contentLength, err := uploads.CalculateRequestSize(buildpackLength, buildpackPath, "buildpack") 162 if err != nil { 163 return nil, err 164 } 165 166 contentType, body, writeErrors := uploads.CreateMultipartBodyAndHeader(buildpack, buildpackPath, "buildpack") 167 168 request, err := client.newHTTPRequest(requestOptions{ 169 RequestName: internal.PutBuildpackBitsRequest, 170 URIParams: Params{"buildpack_guid": buildpackGUID}, 171 Body: body, 172 }) 173 174 if err != nil { 175 return nil, err 176 } 177 178 request.Header.Set("Content-Type", contentType) 179 request.ContentLength = contentLength 180 181 _, warnings, err := client.uploadBuildpackAsynchronously(request, writeErrors) 182 if err != nil { 183 return warnings, err 184 } 185 return warnings, nil 186 } 187 188 func (client *Client) uploadBuildpackAsynchronously(request *cloudcontroller.Request, writeErrors <-chan error) (Buildpack, Warnings, error) { 189 190 var buildpack Buildpack 191 response := cloudcontroller.Response{ 192 DecodeJSONResponseInto: &buildpack, 193 } 194 195 httpErrors := make(chan error) 196 197 go func() { 198 defer close(httpErrors) 199 200 err := client.connection.Make(request, &response) 201 if err != nil { 202 httpErrors <- err 203 } 204 }() 205 206 // The following section makes the following assumptions: 207 // 1) If an error occurs during file reading, an EOF is sent to the request 208 // object. Thus ending the request transfer. 209 // 2) If an error occurs during request transfer, an EOF is sent to the pipe. 210 // Thus ending the writing routine. 211 var firstError error 212 var writeClosed, httpClosed bool 213 214 for { 215 select { 216 case writeErr, ok := <-writeErrors: 217 if !ok { 218 writeClosed = true 219 break // for select 220 } 221 if firstError == nil { 222 firstError = writeErr 223 } 224 case httpErr, ok := <-httpErrors: 225 if !ok { 226 httpClosed = true 227 break // for select 228 } 229 if firstError == nil { 230 firstError = httpErr 231 } 232 } 233 234 if writeClosed && httpClosed { 235 break // for for 236 } 237 } 238 return buildpack, response.Warnings, firstError 239 }