Skip to content

Commit

Permalink
Merge pull request #231 from kool-dev/kub
Browse files Browse the repository at this point in the history
kool deploy exec + refactoring to Kool Deploy API usage/lib client
  • Loading branch information
danielsuguimoto authored Jan 20, 2021
2 parents 311d6dc + 8d319fa commit 24d9156
Show file tree
Hide file tree
Showing 12 changed files with 1,011 additions and 131 deletions.
22 changes: 0 additions & 22 deletions api/api.go
Original file line number Diff line number Diff line change
@@ -1,33 +1,11 @@
package api

import (
"kool-dev/kool/environment"
"net/http"
)

var (
apiBaseURL string = "https://kool.dev/api"
envStorage = environment.NewEnvStorage()
)

// SetBaseURL defines the target Kool API URL to be used
// when reaching out endpoints.
func SetBaseURL(url string) {
apiBaseURL = url
}

func doRequest(request *http.Request) (resp *http.Response, err error) {
var apiToken string = envStorage.Get("KOOL_API_TOKEN")

if apiToken == "" {
err = ErrMissingToken
return
}

request.Header.Add("Accept", "application/json")
request.Header.Add("Authorization", "Bearer "+apiToken)

resp, err = http.DefaultClient.Do(request)

return
}
171 changes: 71 additions & 100 deletions api/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@ package api

import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io"
"io/ioutil"
"kool-dev/kool/environment"
"mime/multipart"
"net/http"
Expand All @@ -16,15 +14,28 @@ import (
// Deploy represents a deployment process, from
// request to finish and retrieving the public URL.
type Deploy struct {
tarballPath, id, Status, url string
Endpoint

tarballPath, id string

env environment.EnvStorage

Status *StatusResponse
}

// DeployResponse holds data returned from the deploy endpoint
type DeployResponse struct {
ID int `json:"id"`
}

// NewDeploy creates a new handler for using the
// Kool Dev API for deploying your application.
func NewDeploy(tarballPath string) (d *Deploy) {
d = new(Deploy)
d.tarballPath = tarballPath
return
func NewDeploy(tarballPath string) *Deploy {
return &Deploy{
Endpoint: newDefaultEndpoint("POST"),
env: environment.NewEnvStorage(),
tarballPath: tarballPath,
}
}

// GetID returns the ID for the deployment
Expand All @@ -34,15 +45,52 @@ func (d *Deploy) GetID() string {

// SendFile calls deploy/create in the Kool Dev API
func (d *Deploy) SendFile() (err error) {
var (
body io.Reader
resp = &DeployResponse{}
)

if body, err = d.getPayload(); err != nil {
return
}

d.SetPath("deploy/create")
d.SetRawBody(body)
d.SetResponseReceiver(resp)
if err = d.DoCall(); err != nil {
return
}

code := d.StatusCode()

if code == http.StatusUnauthorized {
err = ErrUnauthorized
} else if code == http.StatusUnprocessableEntity {
err = ErrPayloadValidation
} else if code != http.StatusOK && code != http.StatusCreated {
err = ErrBadResponseStatus
}

if err != nil {
return
}

d.id = fmt.Sprintf("%d", resp.ID)
if d.id == "0" {
err = errors.New("unexpected API response, please ask for support")
}

return
}

func (d *Deploy) getPayload() (body io.Reader, err error) {
var (
buff bytes.Buffer
file *os.File
fw io.Writer
domain string
domainExtras string
wwwRedirect string
resp *http.Response
raw []byte
)

w := multipart.NewWriter(&buff)
Expand All @@ -54,7 +102,6 @@ func (d *Deploy) SendFile() (err error) {
fi, _ := file.Stat()
fmt.Printf("Release tarball got %.2fMBs...\n", float64(fi.Size())/1024/1024)

// fw, err = w.CreateFormFile("deploy", d.tarballPath)
if fw, err = w.CreateFormFile("deploy", "deploy.tgz"); err != nil {
return
}
Expand All @@ -65,128 +112,52 @@ func (d *Deploy) SendFile() (err error) {

defer file.Close()

if domain = environment.NewEnvStorage().Get("KOOL_DEPLOY_DOMAIN"); domain != "" {
if domain = d.env.Get("KOOL_DEPLOY_DOMAIN"); domain != "" {
if err = w.WriteField("domain", domain); err != nil {
return
}
}

if domainExtras = environment.NewEnvStorage().Get("KOOL_DEPLOY_DOMAIN_EXTRAS"); domainExtras != "" {
if domainExtras = d.env.Get("KOOL_DEPLOY_DOMAIN_EXTRAS"); domainExtras != "" {
if err = w.WriteField("domain_extras", domainExtras); err != nil {
return
}
}

if wwwRedirect = environment.NewEnvStorage().Get("KOOL_DEPLOY_WWW_REDIRECT"); wwwRedirect != "" {
if wwwRedirect = d.env.Get("KOOL_DEPLOY_WWW_REDIRECT"); wwwRedirect != "" {
if err = w.WriteField("www_redirect", wwwRedirect); err != nil {
return
}
}

d.SetContentType(w.FormDataContentType())
w.Close()

req, _ := http.NewRequest("POST", apiBaseURL+"/deploy/create", &buff)
req.Header.Add("Content-Type", w.FormDataContentType())
if resp, err = doRequest(req); err != nil {
return
}

defer resp.Body.Close()

if raw, err = ioutil.ReadAll(resp.Body); err != nil {
return
}

if resp.StatusCode == http.StatusUnauthorized {
err = ErrUnauthorized
} else if resp.StatusCode == http.StatusUnprocessableEntity {
err = ErrPayloadValidation
fmt.Println(string(raw))
} else if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusCreated {
err = ErrBadResponseStatus
fmt.Println(string(raw))
}

if err != nil {
return
}

deploy := make(map[string]interface{})

if err = json.Unmarshal(raw, &deploy); err != nil {
return
}

var (
ok bool
idF float64
)

if idF, ok = deploy["id"].(float64); ok {
d.id = fmt.Sprintf("%d", int64(idF))
} else {
err = errors.New("unexpected API response. Please ask for support")
}

body = &buff
return
}

// GetStatus checks the API for the status of
// the deployment process happening in the
// background.
func (d *Deploy) GetStatus() (err error) {
var (
request *http.Request
resp *http.Response
raw []byte
ok bool
)
request, _ = http.NewRequest("GET", fmt.Sprintf("%s/deploy/%s/status", apiBaseURL, d.id), nil)

if resp, err = doRequest(request); err != nil {
return
}

defer resp.Body.Close()

if raw, err = ioutil.ReadAll(resp.Body); err != nil {
return
}

var data = make(map[string]interface{})

if err = json.Unmarshal(raw, &data); err != nil {
return
}

if d.Status, ok = data["status"].(string); !ok {
err = ErrUnexpectedResponse
// FetchLatestStatus checks the API for the status of the deployment process
// happening in the background
func (d *Deploy) FetchLatestStatus() (err error) {
if d.Status, err = NewDefaultStatusCall(d.id).Call(); err != nil {
return
}

if d.Status == "failed" {
if d.Status.Status == "failed" {
err = ErrDeployFailed
return
}

if d.Status == "success" {
if d.url, ok = data["url"].(string); !ok {
err = ErrUnexpectedResponse
return
}
}

return
}

// IsSuccessful tells whether the deployment
// process finished successfully.
// IsSuccessful tells whether the deployment process finished successfully
func (d *Deploy) IsSuccessful() bool {
return d.Status == "success"
return d.Status.Status == "success"
}

// GetURL returns the generated URL for the deployment
// after it finishes successfully.
// GetURL returns the generated URL for the deployment after it finishes successfully
func (d *Deploy) GetURL() string {
return d.url
return d.Status.URL
}
46 changes: 46 additions & 0 deletions api/deploy_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package api

import (
"kool-dev/kool/environment"
"testing"
)

func TestNewDeploy(t *testing.T) {
var tarball = "tarball"
d := NewDeploy(tarball)

if _, ok := d.env.(*environment.DefaultEnvStorage); !ok {
t.Error("unexpected default environment.EnvStorage")
}

if _, ok := d.Endpoint.(*DefaultEndpoint); !ok {
t.Error("unexpected default Endpoint")
}

if tarball != d.tarballPath {
t.Error("failed setting tarballPath")
}

var id = "id"
d.id = id

if id != d.GetID() {
t.Error("failed setting id")
}

var url = "url"
d.Status = &StatusResponse{Status: "success", URL: url}

if !d.IsSuccessful() {
t.Error("failed asserting success")
}

if url != d.GetURL() {
t.Error("failed getting URL")
}

// still in need of testing
// d.FetchLatestStatus()
// d.SendFile()
// d.getPayload()
}
Loading

0 comments on commit 24d9156

Please sign in to comment.