func UpdateProject(host string, verifyTLS bool, apiKey string, project string, name string, description ...string) (models.ProjectInfo, Error) {
	postBody := map[string]string{"name": name}
	if len(description) > 0 {
		desc := description[0]
		postBody["description"] = desc
	}
	body, err := json.Marshal(postBody)
	if err != nil {
		return models.ProjectInfo{}, Error{Err: err, Message: "Invalid project info"}
	}
	var params []queryParam
	params = append(params, queryParam{Key: "project", Value: project})
	statusCode, _, response, err := PostRequest(host, verifyTLS, apiKeyHeader(apiKey), "/v3/projects/project", params, body)
	if err != nil {
		return models.ProjectInfo{}, Error{Err: err, Message: "Unable to update project", Code: statusCode}
	}
	var result map[string]interface{}
	err = json.Unmarshal(response, &result)
	if err != nil {
		return models.ProjectInfo{}, Error{Err: err, Message: "Unable to parse API response", Code: statusCode}
	}
	resultProject, ok := result["project"].(map[string]interface{})
	if !ok {
		return models.ProjectInfo{}, Error{Err: fmt.Errorf("Unexpected type for project, expected map[string]interface{}, got %T", result["project"]), Message: "Unable to parse API response", Code: statusCode}
	}
	projectInfo := models.ParseProjectInfo(resultProject)
	return projectInfo, Error{}
}
UpdateProject update a project's name and (optional) description
package http
import (
	"encoding/base64"
	"encoding/json"
	"fmt"
	"net/http"
	"time"
	"github.com/DopplerHQ/cli/pkg/models"
	"github.com/DopplerHQ/cli/pkg/version"
)
type Error struct {
	Err     error
	Message string
	Code    int
}
func (e *Error) Unwrap() error { return e.Err }
func (e *Error) IsNil() bool { return e.Err == nil && e.Message == "" }
func apiKeyHeader(apiKey string) map[string]string {
	encoded := base64.StdEncoding.EncodeToString([]byte(apiKey + ":"))
	return map[string]string{"Authorization": fmt.Sprintf("Basic %s", encoded)}
}
func GenerateAuthCode(host string, verifyTLS bool, hostname string, os string, arch string) (map[string]interface{}, Error) {
	var params []queryParam
	params = append(params, queryParam{Key: "hostname", Value: hostname})
	params = append(params, queryParam{Key: "version", Value: version.ProgramVersion})
	params = append(params, queryParam{Key: "os", Value: os})
	params = append(params, queryParam{Key: "arch", Value: arch})
	statusCode, _, response, err := GetRequest(host, verifyTLS, nil, "/v3/auth/cli/generate/2", params)
	if err != nil {
		return nil, Error{Err: err, Message: "Unable to fetch auth code", Code: statusCode}
	}
	var result map[string]interface{}
	err = json.Unmarshal(response, &result)
	if err != nil {
		return nil, Error{Err: err, Message: "Unable to parse API response", Code: statusCode}
	}
	return result, Error{}
}
func GetAuthToken(host string, verifyTLS bool, code string) (map[string]interface{}, Error) {
	reqBody := map[string]interface{}{}
	reqBody["code"] = code
	body, err := json.Marshal(reqBody)
	if err != nil {
		return nil, Error{Err: err, Message: "Invalid auth code"}
	}
	statusCode, _, response, err := PostRequest(host, verifyTLS, nil, "/v3/auth/cli/authorize", []queryParam{}, body)
	if err != nil {
		return nil, Error{Err: err, Message: "Unable to fetch auth token", Code: statusCode}
	}
	var result map[string]interface{}
	err = json.Unmarshal(response, &result)
	if err != nil {
		return nil, Error{Err: err, Message: "Unable to fetch auth token", Code: statusCode}
	}
	return result, Error{}
}
func RollAuthToken(host string, verifyTLS bool, token string) (map[string]interface{}, Error) {
	reqBody := map[string]interface{}{}
	reqBody["token"] = token
	body, err := json.Marshal(reqBody)
	if err != nil {
		return nil, Error{Err: err, Message: "Invalid auth token"}
	}
	statusCode, _, response, err := PostRequest(host, verifyTLS, nil, "/v3/auth/cli/roll", []queryParam{}, body)
	if err != nil {
		return nil, Error{Err: err, Message: "Unable to roll auth token", Code: statusCode}
	}
	var result map[string]interface{}
	err = json.Unmarshal(response, &result)
	if err != nil {
		return nil, Error{Err: err, Message: "Unable to parse API response", Code: statusCode}
	}
	return result, Error{}
}
func RevokeAuthToken(host string, verifyTLS bool, token string) (map[string]interface{}, Error) {
	reqBody := map[string]interface{}{}
	reqBody["token"] = token
	body, err := json.Marshal(reqBody)
	if err != nil {
		return nil, Error{Err: err, Message: "Invalid auth token"}
	}
	statusCode, _, response, err := PostRequest(host, verifyTLS, nil, "/v3/auth/cli/revoke", []queryParam{}, body)
	if err != nil {
		return nil, Error{Err: err, Message: "Unable to revoke auth token", Code: statusCode}
	}
	var result map[string]interface{}
	err = json.Unmarshal(response, &result)
	if err != nil {
		return nil, Error{Err: err, Message: "Unable to parse API response", Code: statusCode}
	}
	return result, Error{}
}
func DownloadSecrets(host string, verifyTLS bool, apiKey string, project string, config string, format models.SecretsFormat, etag string) (int, http.Header, []byte, Error) {
	var params []queryParam
	params = append(params, queryParam{Key: "project", Value: project})
	params = append(params, queryParam{Key: "config", Value: config})
	params = append(params, queryParam{Key: "format", Value: format.String()})
	headers := apiKeyHeader(apiKey)
	if etag != "" {
		headers["If-None-Match"] = etag
	}
	statusCode, respHeaders, response, err := GetRequest(host, verifyTLS, headers, "/v3/configs/config/secrets/download", params)
	if err != nil {
		return statusCode, respHeaders, nil, Error{Err: err, Message: "Unable to download secrets", Code: statusCode}
	}
	return statusCode, respHeaders, response, Error{}
}
func GetSecrets(host string, verifyTLS bool, apiKey string, project string, config string) ([]byte, Error) {
	var params []queryParam
	params = append(params, queryParam{Key: "project", Value: project})
	params = append(params, queryParam{Key: "config", Value: config})
	headers := apiKeyHeader(apiKey)
	headers["Accept"] = "application/json"
	statusCode, _, response, err := GetRequest(host, verifyTLS, headers, "/v3/configs/config/secrets", params)
	if err != nil {
		return nil, Error{Err: err, Message: "Unable to fetch secrets", Code: statusCode}
	}
	return response, Error{}
}
func SetSecrets(host string, verifyTLS bool, apiKey string, project string, config string, secrets map[string]interface{}) (map[string]models.ComputedSecret, Error) {
	reqBody := map[string]interface{}{}
	reqBody["secrets"] = secrets
	body, err := json.Marshal(reqBody)
	if err != nil {
		return nil, Error{Err: err, Message: "Invalid secrets"}
	}
	var params []queryParam
	params = append(params, queryParam{Key: "project", Value: project})
	params = append(params, queryParam{Key: "config", Value: config})
	statusCode, _, response, err := PostRequest(host, verifyTLS, apiKeyHeader(apiKey), "/v3/configs/config/secrets", params, body)
	if err != nil {
		return nil, Error{Err: err, Message: "Unable to set secrets", Code: statusCode}
	}
	var result map[string]interface{}
	err = json.Unmarshal(response, &result)
	if err != nil {
		return nil, Error{Err: err, Message: "Unable to parse API response", Code: statusCode}
	}
	computed := map[string]models.ComputedSecret{}
	for key, secret := range result["secrets"].(map[string]interface{}) {
		val, ok := secret.(map[string]interface{})
		if !ok {
			return nil, Error{Err: fmt.Errorf("Unexpected type mismatch for secret, expected map[string]interface{}, got %T", secret), Message: "Unable to parse API response", Code: statusCode}
		}
		computed[key] = models.ComputedSecret{Name: key, RawValue: val["raw"].(string), ComputedValue: val["computed"].(string)}
	}
	return computed, Error{}
}
func UploadSecrets(host string, verifyTLS bool, apiKey string, project string, config string, secrets string) (map[string]models.ComputedSecret, Error) {
	reqBody := map[string]interface{}{}
	reqBody["file"] = secrets
	body, err := json.Marshal(reqBody)
	if err != nil {
		return nil, Error{Err: err, Message: "Invalid file"}
	}
	var params []queryParam
	params = append(params, queryParam{Key: "project", Value: project})
	params = append(params, queryParam{Key: "config", Value: config})
	statusCode, _, response, err := PostRequest(host, verifyTLS, apiKeyHeader(apiKey), "/v3/configs/config/secrets/upload", params, body)
	if err != nil {
		return nil, Error{Err: err, Message: "Unable to upload secrets", Code: statusCode}
	}
	var result map[string]interface{}
	err = json.Unmarshal(response, &result)
	if err != nil {
		return nil, Error{Err: err, Message: "Unable to parse API response", Code: statusCode}
	}
	computed := map[string]models.ComputedSecret{}
	for key, secret := range result["secrets"].(map[string]interface{}) {
		val, ok := secret.(map[string]interface{})
		if !ok {
			return nil, Error{Err: fmt.Errorf("Unexpected type for secret, expected map[string]interface{}, got %T", secret), Message: "Unable to parse API response", Code: statusCode}
		}
		computed[key] = models.ComputedSecret{Name: key, RawValue: val["raw"].(string), ComputedValue: val["computed"].(string)}
	}
	return computed, Error{}
}
func GetWorkplaceSettings(host string, verifyTLS bool, apiKey string) (models.WorkplaceSettings, Error) {
	statusCode, _, response, err := GetRequest(host, verifyTLS, apiKeyHeader(apiKey), "/workplace/v1", []queryParam{})
	if err != nil {
		return models.WorkplaceSettings{}, Error{Err: err, Message: "Unable to fetch workplace settings", Code: statusCode}
	}
	var result map[string]interface{}
	err = json.Unmarshal(response, &result)
	if err != nil {
		return models.WorkplaceSettings{}, Error{Err: err, Message: "Unable to parse API response", Code: statusCode}
	}
	workplace, ok := result["workplace"].(map[string]interface{})
	if !ok {
		return models.WorkplaceSettings{}, Error{Err: fmt.Errorf("Unexpected type parsing WorkplaceSettings, expected map[string]interface{}, got %T", result["workplace"]), Message: "Unable to parse API response", Code: statusCode}
	}
	settings := models.ParseWorkplaceSettings(workplace)
	return settings, Error{}
}
func SetWorkplaceSettings(host string, verifyTLS bool, apiKey string, values models.WorkplaceSettings) (models.WorkplaceSettings, Error) {
	body, err := json.Marshal(values)
	if err != nil {
		return models.WorkplaceSettings{}, Error{Err: err, Message: "Invalid workplace settings"}
	}
	statusCode, _, response, err := PostRequest(host, verifyTLS, apiKeyHeader(apiKey), "/workplace/v1", []queryParam{}, body)
	if err != nil {
		return models.WorkplaceSettings{}, Error{Err: err, Message: "Unable to update workplace settings", Code: statusCode}
	}
	var result map[string]interface{}
	err = json.Unmarshal(response, &result)
	if err != nil {
		return models.WorkplaceSettings{}, Error{Err: err, Message: "Unable to parse API response", Code: statusCode}
	}
	workplace, ok := result["workplace"].(map[string]interface{})
	if !ok {
		return models.WorkplaceSettings{}, Error{Err: fmt.Errorf("Unexpected type parsing WorkplaceSettings, expected map[string]interface{}, got %T", result["workplace"]), Message: "Unable to parse API response", Code: statusCode}
	}
	settings := models.ParseWorkplaceSettings(workplace)
	return settings, Error{}
}
func GetProjects(host string, verifyTLS bool, apiKey string) ([]models.ProjectInfo, Error) {
	var params []queryParam
	params = append(params, queryParam{Key: "per_page", Value: "100"})
	statusCode, _, response, err := GetRequest(host, verifyTLS, apiKeyHeader(apiKey), "/v3/projects", params)
	if err != nil {
		return nil, Error{Err: err, Message: "Unable to fetch projects", Code: statusCode}
	}
	var result map[string]interface{}
	err = json.Unmarshal(response, &result)
	if err != nil {
		return nil, Error{Err: err, Message: "Unable to parse API response", Code: statusCode}
	}
	var info []models.ProjectInfo
	for _, project := range result["projects"].([]interface{}) {
		project, ok := project.(map[string]interface{})
		if !ok {
			return nil, Error{Err: fmt.Errorf("Unexpected type for project, expected map[string]interface{}, got %T", project), Message: "Unable to parse API response", Code: statusCode}
		}
		projectInfo := models.ParseProjectInfo(project)
		info = append(info, projectInfo)
	}
	return info, Error{}
}
func GetProject(host string, verifyTLS bool, apiKey string, project string) (models.ProjectInfo, Error) {
	var params []queryParam
	params = append(params, queryParam{Key: "project", Value: project})
	statusCode, _, response, err := GetRequest(host, verifyTLS, apiKeyHeader(apiKey), "/v3/projects/project", params)
	if err != nil {
		return models.ProjectInfo{}, Error{Err: err, Message: "Unable to fetch project", Code: statusCode}
	}
	var result map[string]interface{}
	err = json.Unmarshal(response, &result)
	if err != nil {
		return models.ProjectInfo{}, Error{Err: err, Message: "Unable to parse API response", Code: statusCode}
	}
	resultProject, ok := result["project"].(map[string]interface{})
	if !ok {
		return models.ProjectInfo{}, Error{Err: fmt.Errorf("Unexpected type for project, expected map[string]interface{}, got %T", result["project"]), Message: "Unable to parse API response", Code: statusCode}
	}
	projectInfo := models.ParseProjectInfo(resultProject)
	return projectInfo, Error{}
}
func CreateProject(host string, verifyTLS bool, apiKey string, name string, description string) (models.ProjectInfo, Error) {
	postBody := map[string]string{"name": name, "description": description}
	body, err := json.Marshal(postBody)
	if err != nil {
		return models.ProjectInfo{}, Error{Err: err, Message: "Invalid project info"}
	}
	statusCode, _, response, err := PostRequest(host, verifyTLS, apiKeyHeader(apiKey), "/v3/projects", []queryParam{}, body)
	if err != nil {
		return models.ProjectInfo{}, Error{Err: err, Message: "Unable to create project", Code: statusCode}
	}
	var result map[string]interface{}
	err = json.Unmarshal(response, &result)
	if err != nil {
		return models.ProjectInfo{}, Error{Err: err, Message: "Unable to parse API response", Code: statusCode}
	}
	resultProject, ok := result["project"].(map[string]interface{})
	if !ok {
		return models.ProjectInfo{}, Error{Err: fmt.Errorf("Unexpected type for project, expected map[string]interface{}, got %T", result["project"]), Message: "Unable to parse API response", Code: statusCode}
	}
	projectInfo := models.ParseProjectInfo(resultProject)
	return projectInfo, Error{}
}