add http resource create method
This commit is contained in:
parent
01eaf00bb6
commit
11a55e27d0
@ -11,6 +11,9 @@ _ "errors"
|
||||
"net/url"
|
||||
"net/http"
|
||||
_ "os"
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"log/slog"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@ -20,19 +23,26 @@ func init() {
|
||||
|
||||
func HTTPFactory(u *url.URL) Resource {
|
||||
h := NewHTTP()
|
||||
h.Endpoint = u.String()
|
||||
return h
|
||||
}
|
||||
|
||||
type HTTPHeader struct {
|
||||
Name string `yaml:"name" json:"name"`
|
||||
Value string `yaml:"value" json"value"`
|
||||
}
|
||||
|
||||
// Manage the state of an HTTP endpoint
|
||||
type HTTP struct {
|
||||
client *http.Client `yaml:"-" json:"-"`
|
||||
Endpoint string `yaml:"endpoint" json:"endpoint"`
|
||||
|
||||
Headers []HTTPHeader `yaml:"headers,omitempty", json:"headers,omitempty"`
|
||||
Body string `yaml:"body,omitempty" json:"body,omitempty"`
|
||||
State string `yaml:"state" json:"state"`
|
||||
}
|
||||
|
||||
func NewHTTP() *HTTP {
|
||||
return &HTTP{}
|
||||
return &HTTP{ client: &http.Client{} }
|
||||
}
|
||||
|
||||
func (h *HTTP) URI() string {
|
||||
@ -47,36 +57,77 @@ func (h *HTTP) SetURI(uri string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *HTTP) JSON() ([]byte, error) {
|
||||
return json.Marshal(h)
|
||||
}
|
||||
|
||||
func (h *HTTP) Validate() error {
|
||||
return fmt.Errorf("failed")
|
||||
s := NewSchema(h.Type())
|
||||
jsonDoc, jsonErr := h.JSON()
|
||||
if jsonErr == nil {
|
||||
return s.Validate(string(jsonDoc))
|
||||
}
|
||||
return jsonErr
|
||||
}
|
||||
|
||||
func (h *HTTP) Apply() error {
|
||||
|
||||
switch h.State {
|
||||
case "absent":
|
||||
case "present":
|
||||
}
|
||||
|
||||
return nil
|
||||
_,e := h.Read(context.Background())
|
||||
if e == nil {
|
||||
h.State = "present"
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
||||
func (h *HTTP) Load(r io.Reader) error {
|
||||
c := NewYAMLDecoder(r)
|
||||
return c.Decode(h)
|
||||
c := NewYAMLDecoder(r)
|
||||
return c.Decode(h)
|
||||
}
|
||||
|
||||
func (h *HTTP) LoadDecl(yamlResourceDeclaration string) error {
|
||||
c := NewYAMLStringDecoder(yamlResourceDeclaration)
|
||||
return c.Decode(h)
|
||||
slog.Info("LoadDecl()", "yaml", yamlResourceDeclaration)
|
||||
c := NewYAMLStringDecoder(yamlResourceDeclaration)
|
||||
return c.Decode(h)
|
||||
}
|
||||
|
||||
func (h *HTTP) ResolveId(ctx context.Context) string {
|
||||
return h.Endpoint
|
||||
}
|
||||
|
||||
func (h *HTTP) Create() error {
|
||||
body := strings.NewReader(h.Body)
|
||||
req, reqErr := http.NewRequest("POST", h.Endpoint, body)
|
||||
if reqErr != nil {
|
||||
return reqErr
|
||||
}
|
||||
for _,header := range h.Headers {
|
||||
req.Header.Add(header.Name, header.Value)
|
||||
}
|
||||
resp, err := h.client.Do(req)
|
||||
defer resp.Body.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (h *HTTP) Read(ctx context.Context) ([]byte, error) {
|
||||
resp, err := http.Get(h.Endpoint)
|
||||
req, reqErr := http.NewRequestWithContext(ctx, "GET", h.Endpoint, nil)
|
||||
if reqErr != nil {
|
||||
return nil, reqErr
|
||||
}
|
||||
slog.Info("HTTP.Read() ", "request", req, "err", reqErr)
|
||||
|
||||
if len(h.Headers) > 0 {
|
||||
for _,header := range h.Headers {
|
||||
req.Header.Add(header.Name, header.Value)
|
||||
}
|
||||
}
|
||||
|
||||
resp, err := h.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -90,6 +141,5 @@ func (h *HTTP) Read(ctx context.Context) ([]byte, error) {
|
||||
}
|
||||
|
||||
func (h *HTTP) Type() string {
|
||||
u, _ := url.Parse(h.Endpoint)
|
||||
return u.Scheme
|
||||
return "http"
|
||||
}
|
||||
|
@ -3,23 +3,97 @@
|
||||
package resource
|
||||
|
||||
import (
|
||||
_ "context"
|
||||
"context"
|
||||
_ "encoding/json"
|
||||
_ "fmt"
|
||||
"fmt"
|
||||
"github.com/stretchr/testify/assert"
|
||||
_ "gopkg.in/yaml.v3"
|
||||
_ "io"
|
||||
"io"
|
||||
_ "log"
|
||||
_ "net/http"
|
||||
_ "net/http/httptest"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
_ "net/url"
|
||||
_ "os"
|
||||
_ "path/filepath"
|
||||
_ "strings"
|
||||
"testing"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
func TestNewHTTPResource(t *testing.T) {
|
||||
f := NewHTTP()
|
||||
assert.NotNil(t, f)
|
||||
h := NewHTTP()
|
||||
assert.NotNil(t, h)
|
||||
}
|
||||
|
||||
func TestHTTPDecode(t *testing.T) {
|
||||
h := NewHTTP()
|
||||
assert.NotNil(t, h)
|
||||
decl:=`
|
||||
endpoint: "https://example.foo"
|
||||
body: |-
|
||||
test body
|
||||
`
|
||||
|
||||
assert.Nil(t, h.LoadDecl(decl))
|
||||
assert.Equal(t, "test body", h.Body)
|
||||
}
|
||||
|
||||
func TestHTTPRead(t *testing.T) {
|
||||
h := NewHTTP()
|
||||
assert.NotNil(t, h)
|
||||
|
||||
server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||
assert.Equal(t, req.URL.String(), "/resource/user/foo")
|
||||
rw.Write([]byte(`
|
||||
type: "user"
|
||||
attributes:
|
||||
name: "foo"
|
||||
gecos: "foo user"
|
||||
`))
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
decl := fmt.Sprintf(`
|
||||
endpoint: "%s/resource/user/foo"
|
||||
`, server.URL)
|
||||
|
||||
assert.Nil(t, h.LoadDecl(decl))
|
||||
_,e := h.Read(context.Background())
|
||||
assert.Nil(t, e)
|
||||
assert.Greater(t, len(h.Body), 0)
|
||||
assert.Nil(t, h.Validate())
|
||||
}
|
||||
|
||||
func TestHTTPCreate(t *testing.T) {
|
||||
userdecl := `
|
||||
type: "user"
|
||||
attributes:
|
||||
name: "foo"
|
||||
gecos: "foo user"
|
||||
`
|
||||
|
||||
h := NewHTTP()
|
||||
assert.NotNil(t, h)
|
||||
server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||
defer req.Body.Close()
|
||||
assert.Equal(t, req.URL.String(), "/resource/user")
|
||||
body, err := io.ReadAll(req.Body)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, userdecl, string(body))
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
re := regexp.MustCompile(`(?m)^(.*)$`)
|
||||
decl := fmt.Sprintf(`
|
||||
endpoint: "%s/resource/user"
|
||||
headers:
|
||||
- name: "content-type"
|
||||
value: "application/yaml"
|
||||
body: |
|
||||
%s
|
||||
`, server.URL, re.ReplaceAllString(userdecl, " $1"))
|
||||
assert.Nil(t, h.LoadDecl(decl))
|
||||
assert.Greater(t, len(h.Body), 0)
|
||||
e := h.Create()
|
||||
assert.Nil(t, e)
|
||||
}
|
||||
|
@ -12,6 +12,7 @@
|
||||
"oneOf": [
|
||||
{ "$ref": "package-declaration.jsonschema" },
|
||||
{ "$ref": "file-declaration.jsonschema" },
|
||||
{ "$ref": "http-declaration.jsonschema" },
|
||||
{ "$ref": "user-declaration.jsonschema" },
|
||||
{ "$ref": "exec-declaration.jsonschema" },
|
||||
{ "$ref": "network_route-declaration.jsonschema" }
|
||||
|
17
internal/resource/schemas/http-declaration.jsonschema
Normal file
17
internal/resource/schemas/http-declaration.jsonschema
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"$id": "http-declaration.jsonschema",
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "http-declaration",
|
||||
"type": "object",
|
||||
"required": [ "type", "attributes" ],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"description": "Resource type name.",
|
||||
"enum": [ "http" ]
|
||||
},
|
||||
"attributes": {
|
||||
"$ref": "http.jsonschema"
|
||||
}
|
||||
}
|
||||
}
|
31
internal/resource/schemas/http.jsonschema
Normal file
31
internal/resource/schemas/http.jsonschema
Normal file
@ -0,0 +1,31 @@
|
||||
{
|
||||
"$id": "http.jsonschema",
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "http",
|
||||
"type": "object",
|
||||
"required": [ "endpoint" ],
|
||||
"properties": {
|
||||
"endpoint": {
|
||||
"type": "string"
|
||||
},
|
||||
"headers": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "HTTP header name"
|
||||
},
|
||||
"value": {
|
||||
"type": "string",
|
||||
"description": "HTTP header value"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"body": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user