-
Notifications
You must be signed in to change notification settings - Fork 4
/
template_requests.go
174 lines (140 loc) · 5.08 KB
/
template_requests.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
package se2
import (
"bytes"
"context"
"encoding/json"
"fmt"
"net/http"
"github.com/pkg/errors"
)
const (
pathTemplate = "/template/v1"
pathTemplateByName = pathTemplate + "/%s"
pathTemplateImport = pathTemplate + "/import"
)
// ListTemplatesResponse is used to marshal returned json from the SE2 backend into a struct.
type ListTemplatesResponse struct {
Templates []Template `json:"templates"`
}
// Template holds information about a singular template.
type Template struct {
Name string `json:"name"`
Lang string `json:"lang"`
Main string `json:"main,omitempty"`
Version string `json:"api_version"`
}
// ListTemplates will return a ListTemplatesResponse which contains a slice of Template that are available to the
// environment specified by the API key of the client.
func (c *Client) ListTemplates(ctx context.Context) (ListTemplatesResponse, error) {
req, err := http.NewRequestWithContext(ctx, http.MethodGet, c.host+pathTemplate, nil)
if err != nil {
return ListTemplatesResponse{}, errors.Wrap(err, "client.ListTemplates: http.NewRequest")
}
res, err := c.do(req)
if err != nil {
return ListTemplatesResponse{}, errors.Wrap(err, "client.ListTemplates: c.do")
}
defer func() {
_ = res.Body.Close()
}()
if res.StatusCode != http.StatusOK {
return ListTemplatesResponse{}, fmt.Errorf(httpResponseCodeErrorFormat, "client.ListTemplates", http.StatusOK, res.StatusCode)
}
var t ListTemplatesResponse
dec := json.NewDecoder(res.Body)
dec.DisallowUnknownFields()
err = dec.Decode(&t)
if err != nil {
return ListTemplatesResponse{}, errors.Wrap(err, "client.ListTemplates: dec.Decode")
}
return t, nil
}
// GetTemplate takes a name and will return information about a template by that name, or an error if no templates are
// found.
func (c *Client) GetTemplate(ctx context.Context, name string) (Template, error) {
if name == emptyString {
return Template{}, errors.New("client.GetTemplate: name cannot be blank")
}
req, err := http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf(c.host+pathTemplateByName, name), nil)
if err != nil {
return Template{}, errors.Wrap(err, "client.GetTemplate: http.NewRequest")
}
res, err := c.do(req)
if err != nil {
return Template{}, errors.Wrap(err, "client.GetTemplate: c.do")
}
defer func() {
_ = res.Body.Close()
}()
if res.StatusCode != http.StatusOK {
return Template{}, fmt.Errorf(httpResponseCodeErrorFormat, "client.GetTemplate", http.StatusOK, res.StatusCode)
}
var t Template
dec := json.NewDecoder(res.Body)
dec.DisallowUnknownFields()
err = dec.Decode(&t)
if err != nil {
return Template{}, errors.Wrap(err, "client.GetTemplate: dec.Decode")
}
return t, nil
}
// importRequest is an internal shape of the data we need to send to the SE2 backend.
type importRequest struct {
Source string `json:"source"`
Params importParams `json:"params"`
}
// importParams is an internal shape to help describe data to send to the import endpoint on the API.
type importParams struct {
Repo string `json:"repo"`
Ref string `json:"ref"`
Path string `json:"path"`
}
// ImportTemplatesFromGitHub takes a repo, ref, and a path as arguments. It will call the appropriate endpoint on the
// configured SE2 backend. The values are ultimately used to download the source code of a given repository at a given
// reference point - either commit sha or tag reference.
//
// https://github.com/{repo}/archive/{ref}.tar.gz is the pattern.
// ref can take shape in one of the following ways:
// - 755721878465402d2f574635f8b411172f9f8482 (example) if it's a commit sha. At least 6 characters usually works well
// - refs/tags/v0.3.2 if it's a reference to a tag
//
// The repository needs to be publicly accessible; private repositories are not supported. Right now only GitHub is the
// only available provider we can pull source code from.
func (c *Client) ImportTemplatesFromGitHub(ctx context.Context, repo, ref, path string) error {
if repo == emptyString {
return errors.New("client.ImportTemplatesFromGitHub: repo cannot be blank")
}
if ref == emptyString {
return errors.New("client.ImportTemplatesFromGitHub: ref cannot be blank")
}
if path == emptyString {
return errors.New("client.ImportTemplatesFromGitHub: path cannot be blank. If files are on the root of the repository, use '.'")
}
var requestBody bytes.Buffer
err := json.NewEncoder(&requestBody).Encode(importRequest{
Source: "git",
Params: importParams{
Repo: repo,
Ref: ref,
Path: path,
},
})
if err != nil {
return errors.Wrap(err, "client.ImportTemplatesFromGitHub: json.NewEncoder.Encode")
}
req, err := http.NewRequestWithContext(ctx, http.MethodPost, c.host+pathTemplateImport, &requestBody)
if err != nil {
return errors.Wrap(err, "client.ImportTemplatesFromGitHub: http.NewRequest")
}
res, err := c.do(req)
if err != nil {
return errors.Wrap(err, "client.ImportTemplatesFromGitHub: c.do")
}
defer func() {
_ = res.Body.Close()
}()
if res.StatusCode != http.StatusCreated {
return fmt.Errorf(httpResponseCodeErrorFormat, "client.ImportTemplatesFromGitHub", http.StatusOK, res.StatusCode)
}
return nil
}