From e31e91a5adcd708d36175655c325d1dc2901f175 Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Mon, 4 May 2020 22:59:45 -0400 Subject: [PATCH] Add create function template and fix some minor template bugs (#23) --- api/error.go | 3 +- api/error_details.go | 3 +- api/hosts/awsec2_host_catalog.go | 2 +- api/hosts/create.go | 63 +++++++++++++++++++++ api/hosts/host.go | 10 +++- api/hosts/host_catalog.go | 10 +++- api/hosts/host_set.go | 10 +++- api/hosts/static_host_catalog.go | 2 +- api/internal/genapi/create.go | 95 ++++++++++++++++++++++++++++++++ api/internal/genapi/input.go | 4 +- api/internal/genapi/main.go | 3 +- api/internal/genapi/templates.go | 23 +++++--- 12 files changed, 204 insertions(+), 24 deletions(-) create mode 100644 api/hosts/create.go create mode 100644 api/internal/genapi/create.go diff --git a/api/error.go b/api/error.go index eec9c7e71d..9af1599bea 100644 --- a/api/error.go +++ b/api/error.go @@ -1,10 +1,11 @@ -// Code generated by go generate; DO NOT EDIT. +// Code generated by "make api"; DO NOT EDIT. package api import ( "encoding/json" "github.com/fatih/structs" + "github.com/hashicorp/watchtower/api/internal/strutil" ) diff --git a/api/error_details.go b/api/error_details.go index aa8ca392e3..fd25438210 100644 --- a/api/error_details.go +++ b/api/error_details.go @@ -1,10 +1,11 @@ -// Code generated by go generate; DO NOT EDIT. +// Code generated by "make api"; DO NOT EDIT. package api import ( "encoding/json" "github.com/fatih/structs" + "github.com/hashicorp/watchtower/api/internal/strutil" ) diff --git a/api/hosts/awsec2_host_catalog.go b/api/hosts/awsec2_host_catalog.go index 20fda90378..44aeb1b152 100644 --- a/api/hosts/awsec2_host_catalog.go +++ b/api/hosts/awsec2_host_catalog.go @@ -1,4 +1,4 @@ -// Code generated by go generate; DO NOT EDIT. +// Code generated by "make api"; DO NOT EDIT. package hosts import ( diff --git a/api/hosts/create.go b/api/hosts/create.go new file mode 100644 index 0000000000..d7eba91f3b --- /dev/null +++ b/api/hosts/create.go @@ -0,0 +1,63 @@ +// Code generated by "make api"; DO NOT EDIT. +package hosts + +import ( + "context" + "fmt" + + "github.com/hashicorp/watchtower/api" +) + +func (s HostCatalog) CreateHost(ctx context.Context, host *Host) (*Host, *api.Error, error) { + if s.Client == nil { + return nil, nil, fmt.Errorf("nil client in CreateHost request") + } + if s.Id == nil || *s.Id == "" { + return nil, nil, fmt.Errorf("missing catalog ID in CreateHost request") + } + + req, err := s.Client.NewRequest(ctx, "PUT", fmt.Sprintf("host-catalogs/%s/hosts", *s.Id), host) + if err != nil { + return nil, nil, fmt.Errorf("error creating CreateHost request: %w", err) + } + + resp, err := s.Client.Do(req) + if err != nil { + return nil, nil, fmt.Errorf("error performing client request during CreateHost call: %w", err) + } + + target := new(Host) + apiErr, err := resp.Decode(target) + if err != nil { + return nil, nil, fmt.Errorf("error decoding CreateHost repsonse: %w", err) + } + + return target, apiErr, nil +} + +func (s HostCatalog) CreateHostSet(ctx context.Context, hostset *HostSet) (*HostSet, *api.Error, error) { + if s.Client == nil { + return nil, nil, fmt.Errorf("nil client in CreateHostSet request") + } + if s.Id == nil || *s.Id == "" { + return nil, nil, fmt.Errorf("missing catalog ID in CreateHostSet request") + } + + req, err := s.Client.NewRequest(ctx, "PUT", fmt.Sprintf("host-catalogs/%s/host-sets", *s.Id), hostset) + if err != nil { + return nil, nil, fmt.Errorf("error creating CreateHostSet request: %w", err) + } + + resp, err := s.Client.Do(req) + if err != nil { + return nil, nil, fmt.Errorf("error performing client request during CreateHostSet call: %w", err) + } + + target := new(HostSet) + apiErr, err := resp.Decode(target) + if err != nil { + return nil, nil, fmt.Errorf("error decoding CreateHostSet repsonse: %w", err) + } + + return target, apiErr, nil +} diff --git a/api/hosts/host.go b/api/hosts/host.go index fba129f022..f696be3d66 100644 --- a/api/hosts/host.go +++ b/api/hosts/host.go @@ -1,4 +1,4 @@ -// Code generated by go generate; DO NOT EDIT. +// Code generated by "make api"; DO NOT EDIT. package hosts import ( @@ -6,15 +6,19 @@ import ( "time" "github.com/fatih/structs" + + "github.com/hashicorp/watchtower/api" "github.com/hashicorp/watchtower/api/internal/strutil" ) type Host struct { + Client *api.Client `json:"-"` + defaultFields []string - // Canonical path of the resource from the API's base URI + // The ID of the host // Output only. - Path *string `json:"path,omitempty"` + Id *string `json:"id,omitempty"` // The type of the resource, to help differentiate schemas Type *string `json:"type,omitempty"` // Friendly name, if set diff --git a/api/hosts/host_catalog.go b/api/hosts/host_catalog.go index 1810d47f57..278e3d1dc2 100644 --- a/api/hosts/host_catalog.go +++ b/api/hosts/host_catalog.go @@ -1,4 +1,4 @@ -// Code generated by go generate; DO NOT EDIT. +// Code generated by "make api"; DO NOT EDIT. package hosts import ( @@ -6,15 +6,19 @@ import ( "time" "github.com/fatih/structs" + + "github.com/hashicorp/watchtower/api" "github.com/hashicorp/watchtower/api/internal/strutil" ) type HostCatalog struct { + Client *api.Client `json:"-"` + defaultFields []string - // Canonical path of the resource from the API's base URI + // The ID of the host // Output only. - Path *string `json:"path,omitempty"` + Id *string `json:"id,omitempty"` // The type of the resource, to help differentiate schemas Type *string `json:"type,omitempty"` // Friendly name, if set diff --git a/api/hosts/host_set.go b/api/hosts/host_set.go index f846832904..b6c7127aeb 100644 --- a/api/hosts/host_set.go +++ b/api/hosts/host_set.go @@ -1,4 +1,4 @@ -// Code generated by go generate; DO NOT EDIT. +// Code generated by "make api"; DO NOT EDIT. package hosts import ( @@ -6,15 +6,19 @@ import ( "time" "github.com/fatih/structs" + + "github.com/hashicorp/watchtower/api" "github.com/hashicorp/watchtower/api/internal/strutil" ) type HostSet struct { + Client *api.Client `json:"-"` + defaultFields []string - // Canonical path of the resource from the API's base URI + // The ID of the host // Output only. - Path *string `json:"path,omitempty"` + Id *string `json:"id,omitempty"` // The type of the resource, to help differentiate schemas Type *string `json:"type,omitempty"` // Friendly name, if set diff --git a/api/hosts/static_host_catalog.go b/api/hosts/static_host_catalog.go index 1db1d3bb19..210ac120ba 100644 --- a/api/hosts/static_host_catalog.go +++ b/api/hosts/static_host_catalog.go @@ -1,4 +1,4 @@ -// Code generated by go generate; DO NOT EDIT. +// Code generated by "make api"; DO NOT EDIT. package hosts import ( diff --git a/api/internal/genapi/create.go b/api/internal/genapi/create.go new file mode 100644 index 0000000000..2c9f153a0a --- /dev/null +++ b/api/internal/genapi/create.go @@ -0,0 +1,95 @@ +// +build genapi + +package main + +import ( + "bytes" + "fmt" + "io/ioutil" + "os" + "strings" + "text/template" +) + +type createInfo struct { + baseType string + targetType string + verb string + path string +} + +var createFuncs = map[string][]*createInfo{ + "hosts": { + { + "HostCatalog", + "Host", + "PUT", + "host-catalogs/%s/hosts", + }, + { + "HostCatalog", + "HostSet", + "PUT", + "host-catalogs/%s/host-sets", + }, + }, +} + +func writeCreateFuncs() { + for outPkg, funcs := range createFuncs { + outFile := os.Getenv("APIGEN_BASEPATH") + fmt.Sprintf("/api/%s/create.go", outPkg) + outBuf := bytes.NewBuffer([]byte(fmt.Sprintf( + `// Code generated by "make api"; DO NOT EDIT. +package %s +`, outPkg))) + for _, createInfo := range funcs { + createFuncTemplate.Execute(outBuf, struct { + BaseType string + TargetType string + LowerTargetType string + Verb string + Path string + }{ + BaseType: createInfo.baseType, + TargetType: createInfo.targetType, + LowerTargetType: strings.ToLower(createInfo.targetType), + Verb: createInfo.verb, + Path: createInfo.path, + }) + } + if err := ioutil.WriteFile(outFile, outBuf.Bytes(), 0644); err != nil { + fmt.Printf("error writing file %q: %v\n", outFile, err) + os.Exit(1) + } + } +} + +var createFuncTemplate = template.Must(template.New("").Parse( + ` +func (s {{ .BaseType }}) Create{{ .TargetType }}(ctx context.Context, {{ .LowerTargetType }} *{{ .TargetType }}) (*{{ .TargetType }}, *api.Error, error) { + if s.Client == nil { + return nil, nil, fmt.Errorf("nil client in Create{{ .TargetType }} request") + } + if s.Id == nil || *s.Id == "" { + return nil, nil, fmt.Errorf("missing catalog ID in Create{{ .TargetType }} request") + } + + req, err := s.Client.NewRequest(ctx, "{{ .Verb }}", fmt.Sprintf("{{ .Path }}", *s.Id), {{ .LowerTargetType }}) + if err != nil { + return nil, nil, fmt.Errorf("error creating Create{{ .TargetType }} request: %w", err) + } + + resp, err := s.Client.Do(req) + if err != nil { + return nil, nil, fmt.Errorf("error performing client request during Create{{ .TargetType }} call: %w", err) + } + + target := new({{ .TargetType }}) + apiErr, err := resp.Decode(target) + if err != nil { + return nil, nil, fmt.Errorf("error decoding Create{{ .TargetType }} repsonse: %w", err) + } + + return target, apiErr, nil +} + `)) diff --git a/api/internal/genapi/input.go b/api/internal/genapi/input.go index b35fd988ac..c0cc4898f5 100644 --- a/api/internal/genapi/input.go +++ b/api/internal/genapi/input.go @@ -4,7 +4,7 @@ package main import "os" -type generateInfo struct { +type structInfo struct { inFile string inName string outFile string @@ -16,7 +16,7 @@ type generateInfo struct { templateType templateType } -var inputStructs = []*generateInfo{ +var inputStructs = []*structInfo{ { os.Getenv("APIGEN_BASEPATH") + "/internal/gen/controller/api/error.pb.go", "Error", diff --git a/api/internal/genapi/main.go b/api/internal/genapi/main.go index d5b1ff3e20..8784c85e2c 100644 --- a/api/internal/genapi/main.go +++ b/api/internal/genapi/main.go @@ -4,5 +4,6 @@ package main func main() { parsePBs() - writeTemplates() + writeStructTemplates() + writeCreateFuncs() } diff --git a/api/internal/genapi/templates.go b/api/internal/genapi/templates.go index 72c252a865..2897998ac8 100644 --- a/api/internal/genapi/templates.go +++ b/api/internal/genapi/templates.go @@ -9,7 +9,6 @@ import ( "os" "path/filepath" "text/template" - "time" ) type templateType int @@ -19,13 +18,12 @@ const ( templateTypeDetail ) -func writeTemplates() { +func writeStructTemplates() { for _, inputStruct := range inputStructs { outBuf := new(bytes.Buffer) switch inputStruct.templateType { case templateTypeResource: - utilFuncsTemplate.Execute(outBuf, struct { - Timestamp time.Time + structTemplate.Execute(outBuf, struct { Name string Package string StructFields string @@ -37,7 +35,6 @@ func writeTemplates() { case templateTypeDetail: detailTemplate.Execute(outBuf, struct { - Timestamp time.Time Package string StructFields string ParentName string @@ -63,18 +60,25 @@ func writeTemplates() { } } -var utilFuncsTemplate = template.Must(template.New("").Parse( - `// Code generated by go generate; DO NOT EDIT. +var structTemplate = template.Must(template.New("").Parse( + `// Code generated by "make api"; DO NOT EDIT. package {{ .Package }} import ( + "context" "encoding/json" "github.com/fatih/structs" + + "github.com/hashicorp/watchtower/api" "github.com/hashicorp/watchtower/api/internal/strutil" ) type {{ .Name }} struct { + {{ if (not (eq .Package "api")) }} + Client *api.Client ` + "`json:\"-\"`" + ` + {{ end }} + {{ .StructFields }} } @@ -99,17 +103,20 @@ func (s {{ .Name }}) MarshalJSON() ([]byte, error) { `)) var detailTemplate = template.Must(template.New("").Parse( - `// Code generated by go generate; DO NOT EDIT. + `// Code generated by "make api"; DO NOT EDIT. package {{ .Package }} import ( "fmt" "github.com/mitchellh/mapstructure" + + "github.com/hashicorp/watchtower/api" ) type {{ .DetailName }} struct { *{{ .ParentName }} + {{ .StructFields }} }