mirror of https://github.com/k3s-io/k3s
111 lines
3.2 KiB
Go
111 lines
3.2 KiB
Go
// Copyright (c) 2016 VMware, Inc. All Rights Reserved.
|
|
//
|
|
// This product is licensed to you under the Apache License, Version 2.0 (the "License").
|
|
// You may not use this product except in compliance with the License.
|
|
//
|
|
// This product may include a number of subcomponents with separate copyright notices and
|
|
// license terms. Your use of these subcomponents is subject to the terms and conditions
|
|
// of the subcomponent's license, as noted in the LICENSE file.
|
|
|
|
package photon
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"net/http"
|
|
"net/url"
|
|
"reflect"
|
|
)
|
|
|
|
// Reads an error out of the HTTP response, or does nothing if
|
|
// no error occured.
|
|
func getError(res *http.Response) (*http.Response, error) {
|
|
// Do nothing if the response is a successful 2xx
|
|
if res.StatusCode/100 == 2 {
|
|
return res, nil
|
|
}
|
|
var apiError ApiError
|
|
// ReadAll is usually a bad practice, but here we need to read the response all
|
|
// at once because we may attempt to use the data twice. It's preferable to use
|
|
// methods that take io.Reader, e.g. json.NewDecoder
|
|
body, err := ioutil.ReadAll(res.Body)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
err = json.Unmarshal(body, &apiError)
|
|
if err != nil {
|
|
// If deserializing into ApiError fails, return a generic HttpError instead
|
|
return nil, HttpError{res.StatusCode, string(body[:])}
|
|
}
|
|
apiError.HttpStatusCode = res.StatusCode
|
|
return nil, apiError
|
|
}
|
|
|
|
// Reads a task object out of the HTTP response. Takes an error argument
|
|
// so that GetTask can easily wrap GetError. This function will do nothing
|
|
// if e is not nil.
|
|
// e.g. res, err := getTask(getError(someApi.Get()))
|
|
func getTask(res *http.Response, e error) (*Task, error) {
|
|
if e != nil {
|
|
return nil, e
|
|
}
|
|
var task Task
|
|
err := json.NewDecoder(res.Body).Decode(&task)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if task.State == "ERROR" {
|
|
// Critical: return task as well, so that it can be examined
|
|
// for error details.
|
|
return &task, TaskError{task.ID, getFailedStep(&task)}
|
|
}
|
|
return &task, nil
|
|
}
|
|
|
|
// Converts an options struct into a query string.
|
|
// E.g. type Foo struct {A int; B int} might return "?a=5&b=10".
|
|
// Will return an empty string if no options are set.
|
|
func getQueryString(options interface{}) string {
|
|
buffer := bytes.Buffer{}
|
|
buffer.WriteString("?")
|
|
strct := reflect.ValueOf(options).Elem()
|
|
typ := strct.Type()
|
|
for i := 0; i < strct.NumField(); i++ {
|
|
field := strct.Field(i)
|
|
value := fmt.Sprint(field.Interface())
|
|
if value != "" {
|
|
buffer.WriteString(typ.Field(i).Tag.Get("urlParam") + "=" + url.QueryEscape(value))
|
|
if i < strct.NumField()-1 {
|
|
buffer.WriteString("&")
|
|
}
|
|
}
|
|
}
|
|
uri := buffer.String()
|
|
if uri == "?" {
|
|
return ""
|
|
}
|
|
return uri
|
|
}
|
|
|
|
// Sets security groups for a given entity (deployment/tenant/project)
|
|
func setSecurityGroups(client *Client, entityUrl string, securityGroups *SecurityGroupsSpec) (task *Task, err error) {
|
|
body, err := json.Marshal(securityGroups)
|
|
if err != nil {
|
|
return
|
|
}
|
|
url := entityUrl + "/set_security_groups"
|
|
res, err := client.restClient.Post(
|
|
url,
|
|
"application/json",
|
|
bytes.NewReader(body),
|
|
client.options.TokenOptions.AccessToken)
|
|
if err != nil {
|
|
return
|
|
}
|
|
defer res.Body.Close()
|
|
task, err = getTask(getError(res))
|
|
return
|
|
}
|