Skip to content

Split client and provider into separate packages #2

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Jun 9, 2020
92 changes: 92 additions & 0 deletions client/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package client

import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strings"
)

// Client token, host, htpp.Client
type Client struct {
Token string
Host string
Client *http.Client
}

// RequestOptions path, method, etc
type RequestOptions struct {
Path string
Method string
Body []byte
QS map[string]string
}

// NewClient returns a new client configured to communicate on a server with the
// given hostname and to send an Authorization Header with the value of
// token
func NewClient(hostname string, token string) *Client {
return &Client{
Host: hostname,
Token: token,
Client: &http.Client{},
}

}

// RequestAPI http request to Codefresh API
func (client *Client) RequestAPI(opt *RequestOptions) ([]byte, error) {
finalURL := fmt.Sprintf("%s%s", client.Host, opt.Path)
if opt.QS != nil {
finalURL += ToQS(opt.QS)
}
request, err := http.NewRequest(opt.Method, finalURL, bytes.NewBuffer(opt.Body))
if err != nil {
return nil, err
}

request.Header.Set("Authorization", client.Token)
request.Header.Set("Content-Type", "application/json; charset=utf-8")

resp, err := client.Client.Do(request)

if err != nil {
return nil, err
}
defer resp.Body.Close()

body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("Failed to read body %v %v", resp.StatusCode, resp.Status)
}

if resp.StatusCode != 200 {
return nil, fmt.Errorf("%v, %s", resp.Status, string(body))
}
return body, nil
}

// ToQS add extra parameters to path
func ToQS(qs map[string]string) string {
var arr = []string{}
for k, v := range qs {
arr = append(arr, fmt.Sprintf("%s=%s", k, v))
}
return "?" + strings.Join(arr, "&")
}

// DecodeResponseInto json Unmarshall
func DecodeResponseInto(body []byte, target interface{}) error {
return json.Unmarshal(body, target)
}

// EncodeToJSON json Marshal
func EncodeToJSON(object interface{}) ([]byte, error) {
body, err := json.Marshal(object)
if err != nil {
return nil, err
}
return body, nil
}
198 changes: 198 additions & 0 deletions client/pipeline.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
package client

import (
"errors"
"fmt"
"strings"
)

type ErrorResponse struct {
Status int `json:"status,omitempty"`
Message string `json:"message,omitempty"`
Error string `json:"error,omitempty"`
}

type Labels struct {
Tags []string `json:"tags,omitempty"`
}

type Metadata struct {
Name string `json:"name,omitempty"`
ID string `json:"id,omitempty"`
Labels Labels `json:"labels,omitempty"`
OriginalYamlString string `json:"originalYamlString,omitempty"`
Project string `json:"project,omitempty"`
ProjectId string `json:"projectId,omitempty"`
Revision int `json:"revision,omitempty"`
}

type SpecTemplate struct {
Location string `json:"location,omitempty"`
Repo string `json:"repo,omitempty"`
Path string `json:"path,omitempty"`
Revision string `json:"revision,omitempty"`
Context string `json:"context,omitempty"`
}

type Trigger struct {
Name string `json:"name,omitempty"`
Description string `json:"description,omitempty"`
Type string `json:"type,omitempty"`
Repo string `json:"repo,omitempty"`
Events []string `json:"events,omitempty"`
BranchRegex string `json:"branchRegex,omitempty"`
ModifiedFilesGlob string `json:"modifiedFilesGlob,omitempty"`
Provider string `json:"provider,omitempty"`
Disabled bool `json:"disabled,omitempty"`
Context string `json:"context,omitempty"`
Variables []Variable `json:"variables,omitempty"`
}

type RuntimeEnvironment struct {
Name string `json:"name,omitempty"`
Memory string `json:"memory,omitempty"`
CPU string `json:"cpu,omitempty"`
DindStorage string `json:"dindStorage,omitempty"`
}

func (t *Trigger) SetVariables(variables map[string]string) {
for key, value := range variables {
t.Variables = append(t.Variables, Variable{Key: key, Value: value})
}
}

type Spec struct {
Variables []Variable `json:"variables,omitempty"`
SpecTemplate *SpecTemplate `json:"specTemplate,omitempty"`
Triggers []Trigger `json:"triggers,omitempty"`
Priority int `json:"priority,omitempty"`
Concurrency int `json:"concurrency,omitempty"`
Contexts []interface{} `json:"contexts,omitempty"`
Steps map[string]interface{} `json:"steps,omitempty"`
Stages []interface{} `json:"stages,omitempty"`
Mode string `json:"mode,omitempty"`
RuntimeEnvironment RuntimeEnvironment `json:"runtimeEnvironment,omitempty"`
}

type Pipeline struct {
Metadata Metadata `json:"metadata,omitempty"`
Spec Spec `json:"spec,omitempty"`
Version string `json:"version,omitempty"`
}

func (p *Pipeline) SetVariables(variables map[string]string) {
for key, value := range variables {
p.Spec.Variables = append(p.Spec.Variables, Variable{Key: key, Value: value})
}
}

func (pipeline *Pipeline) GetID() string {
if pipeline.Metadata.ID != "" {
return pipeline.Metadata.ID
} else {
return pipeline.Metadata.Name
}
}

func (client *Client) GetPipeline(name string) (*Pipeline, error) {
fullPath := fmt.Sprintf("/pipelines/%s", strings.Replace(name, "/", "%2F", 1))
opts := RequestOptions{
Path: fullPath,
Method: "GET",
}

resp, err := client.RequestAPI(&opts)

if err != nil {
return nil, err
}

var pipeline Pipeline

err = DecodeResponseInto(resp, &pipeline)
if err != nil {
return nil, err
}

return &pipeline, nil
}

func (client *Client) CreatePipeline(pipeline *Pipeline) (*Pipeline, error) {

body, err := EncodeToJSON(pipeline)

if err != nil {
return nil, err
}
opts := RequestOptions{
Path: "/pipelines",
Method: "POST",
Body: body,
}

resp, err := client.RequestAPI(&opts)

if err != nil {
return nil, err
}

var respPipeline Pipeline
err = DecodeResponseInto(resp, &respPipeline)
if err != nil {
return nil, err
}

return &respPipeline, nil

}

func (client *Client) UpdatePipeline(pipeline *Pipeline) (*Pipeline, error) {

body, err := EncodeToJSON(pipeline)

if err != nil {
return nil, err
}

id := pipeline.GetID()
if id == "" {
return nil, errors.New("[ERROR] Both Pipeline ID and Name are empty")
}

fullPath := fmt.Sprintf("/pipelines/%s", strings.Replace(id, "/", "%2F", 1))
opts := RequestOptions{
Path: fullPath,
Method: "PUT",
Body: body,
}

resp, err := client.RequestAPI(&opts)
if err != nil {
return nil, err
}

var respPipeline Pipeline
err = DecodeResponseInto(resp, &respPipeline)
if err != nil {
return nil, err
}

return &respPipeline, nil
}

func (client *Client) DeletePipeline(name string) error {

fullPath := fmt.Sprintf("/pipelines/%s", strings.Replace(name, "/", "%2F", 1))
opts := RequestOptions{
Path: fullPath,
Method: "DELETE",
}

_, err := client.RequestAPI(&opts)

if err != nil {
return err
}

return nil
}
Loading