Fix Update Project Logic (#54)
* carve out scope into a separate branch for a PR * refactor getOpts to be private * narrowed to just the scope proto * wrap in a transaction * remove user from scopes PR * make scope type immutable * refactored with more referential integrity (thanks mike) * refactor based on pair programming with Mike * better VetForWrite that supports db.Options but that requires GetOpts and Options to be exported. * stop printing out all the db logs * refactor withScope to be private * refactor the VetForWrite a bit based on Todd's PR comment * fix typo Co-authored-by: Michael Gaffney <mgaffney@users.noreply.github.com> * fix ctx propagation and Scope returns * fix ctx propagation and use a const for std retry count * change Std to Crud * fix ctx propagation * make sure update with field masks doesn't update a field not in the mask and force a read after update. * add description * remove comment about future * clean error strings * clean up enum string rep * stdMeta * fix return value to be just nil * fix returns and errors * update test to match new error string * change len of domain to 24 * provide common function for new public ids * use common db.NewPublicId() and provide the correct prefix * move list out of CrudActions and provide a CrudlActions shortcut as well * some comments about the purpose of VetForWrite() * move to random 10 * Adding project API interface. * Creation of Project handler and Tests * Move to using the iam objects. * Setting up testify framework for mocking and assertions. * Fix iam options typo references. * Adding tests for CreateProject and UpdateProject. This also adds some additional argument validation. * Merging in PR 40 * Renamed fakeRepo to mockRepo * Changing around TODOs to capture current plans with the code. * Remove the repo interface and use a real DB for tests. * Fixed a few tests. * Adding checks for properly formatted identifiers. * Updating code to account for recent merges. Relaxing some restrictions on what an id can look like. * Added small comment explaining why RegisterGrpcGatewayer interface exists. * Move project service up a call level. Long term I think it would make sense to define these services even higher up the call stack, potentially at the initialization of the controller server, near where the DB is initialized. * Making these fields align with those in the resources under hosts/... * Hard code the service initialization in the handler registration code. * Regenerate project related code proto code. * Removing type field for project. * Adds basic project handling in CLI/SDK (#47) * Adds SDK for creating and reading projects * Reorganizes a bit * Adds CLI for creating and reading projects * Fixes some some generation bugs * Adds redirect support for default org ID * Fix protobuf import references being moved. * Update client test to look for "orgs" and "projects" instead of "org" and "project" * Update expected segments test * Fix setAddr handling when default organization is in use * Set client in target after create or read * Adding functionality and tests for update masks. * Additional tests for update. Disable update non existant project test. * Make not providing an update mask be an invalid argument. * Make empty update mask paths and no mutable fields in the path an InvalidArgument error. * Fix get Project test. * Adding back in the Update a non existant project test case. * Adding seperate path structured tests. * Attach an issue id to field mask validation TODO. * Generate Project Update SDK code (#58) * Created the UpdateFunction method. * Regenerate protobuf derived code since pull #50 updated dependencies. * Special case IDs to not be passed for updates. * Updated the tools file since imports reordered it. * Add spaces between each tools import/comment grouping. Co-authored-by: Jim Lambert <jimlambrt@Jims-MBP-3.home> Co-authored-by: Jim <jlambert@hashicorp.com> Co-authored-by: Michael Gaffney <mgaffney@users.noreply.github.com> Co-authored-by: Jeff Mitchell <jeffrey.mitchell@gmail.com>
This commit is contained in:
31 files changed
+542
-101
No files matched your search
@@ -5,4 +5,5 @@ func main() {
|
||||
writeStructTemplates()
|
||||
writeCreateFuncs()
|
||||
writeReadFuncs()
|
||||
writeUpdateFuncs()
|
||||
}
|
||||
@@ -58,6 +58,7 @@ func writeStructTemplates() {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Add documentation around SetDefault and how it behaves when the field corresponding to the provided key is already set.
|
||||
var structTemplate = template.Must(template.New("").Parse(
|
||||
`// Code generated by "make api"; DO NOT EDIT.
|
||||
package {{ .Package }}
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
type updateInfo struct {
|
||||
baseType string
|
||||
targetType string
|
||||
path string
|
||||
}
|
||||
|
||||
var updateFuncs = map[string][]*updateInfo{
|
||||
"scopes": {
|
||||
{
|
||||
"Organization",
|
||||
"Project",
|
||||
"projects/%s",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func writeUpdateFuncs() {
|
||||
for outPkg, funcs := range updateFuncs {
|
||||
outFile := os.Getenv("GEN_BASEPATH") + fmt.Sprintf("/api/%s/update.gen.go", outPkg)
|
||||
outBuf := bytes.NewBuffer([]byte(fmt.Sprintf(
|
||||
`// Code generated by "make api"; DO NOT EDIT.
|
||||
package %s
|
||||
`, outPkg)))
|
||||
for _, updateInfo := range funcs {
|
||||
updateFuncTemplate.Execute(outBuf, struct {
|
||||
BaseType string
|
||||
TargetType string
|
||||
LowerTargetType string
|
||||
Path string
|
||||
}{
|
||||
BaseType: updateInfo.baseType,
|
||||
TargetType: updateInfo.targetType,
|
||||
LowerTargetType: strings.ToLower(updateInfo.targetType),
|
||||
Path: updateInfo.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 updateFuncTemplate = template.Must(template.New("").Parse(
|
||||
`
|
||||
func (s {{ .BaseType }}) Update{{ .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 == "" {
|
||||
{{ if (eq .BaseType "Organization") }}
|
||||
// Assume the client has been configured with organization already and
|
||||
// move on
|
||||
{{ else if (eq .BaseType "Project") }}
|
||||
// Assume the client has been configured with project already and move
|
||||
// on
|
||||
{{ else }}
|
||||
return nil, nil, fmt.Errorf("missing {{ .BaseType}} ID in Create{{ .TargetType }} request")
|
||||
{{ end }}
|
||||
} else {
|
||||
// If it's explicitly set here, override anything that might be in the
|
||||
// client
|
||||
{{ if (eq .BaseType "Organization") }}
|
||||
ctx = context.WithValue(ctx, "org", s.Id)
|
||||
{{ else if (eq .BaseType "Project") }}
|
||||
ctx = context.WithValue(ctx, "project", s.Id)
|
||||
{{ end }}
|
||||
}
|
||||
|
||||
id := {{ .LowerTargetType }}.Id
|
||||
{{ .LowerTargetType }}.Id = ""
|
||||
|
||||
req, err := s.Client.NewRequest(ctx, "PATCH", fmt.Sprintf("{{ .Path }}", 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 Update{{ .TargetType }} call: %w", err)
|
||||
}
|
||||
|
||||
target := new({{ .TargetType }})
|
||||
apiErr, err := resp.Decode(target)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error decoding Update{{ .TargetType }} repsonse: %w", err)
|
||||
}
|
||||
|
||||
{{ if (eq .TargetType "Organization") }}
|
||||
target.Client = s.Client.Clone()
|
||||
target.Client.SetOrgnization(target.Id)
|
||||
{{ else if (eq .TargetType "Project") }}
|
||||
target.Client = s.Client.Clone()
|
||||
target.Client.SetProject(target.Id)
|
||||
{{ else }}
|
||||
target.Client = s.Client
|
||||
{{ end }}
|
||||
|
||||
return target, apiErr, nil
|
||||
}
|
||||
`))
|
||||
@@ -17,24 +17,26 @@ func TestProjects_Crud(t *testing.T) {
|
||||
Client: client,
|
||||
}
|
||||
|
||||
name := "foo"
|
||||
|
||||
checkProject := func(step string, p *Project, apiErr *api.Error, err error) {
|
||||
checkProject := func(step string, p *Project, apiErr *api.Error, err error, wantedName string) {
|
||||
assert := assert.New(t)
|
||||
assert.NoError(err, step)
|
||||
assert.Nil(apiErr, step)
|
||||
assert.NotNil(p, "returned project", step)
|
||||
assert.NotNil(p, "returned project name", step)
|
||||
assert.Equal(name, *p.Name, step)
|
||||
assert.Equal(wantedName, *p.Name, step)
|
||||
}
|
||||
|
||||
p, apiErr, err := org.CreateProject(tc.Context(), &Project{Name: api.String(name)})
|
||||
checkProject("create", p, apiErr, err)
|
||||
p, apiErr, err := org.CreateProject(tc.Context(), &Project{Name: api.String("foo")})
|
||||
checkProject("create", p, apiErr, err, "foo")
|
||||
|
||||
p, apiErr, err = org.ReadProject(tc.Context(), &Project{Id: p.Id})
|
||||
checkProject("read", p, apiErr, err)
|
||||
checkProject("read", p, apiErr, err, "foo")
|
||||
|
||||
// TODO: Update and Delete
|
||||
p = &Project{Id: p.Id}
|
||||
p.Name = api.String("bar")
|
||||
p, apiErr, err = org.UpdateProject(tc.Context(), p)
|
||||
checkProject("update", p, apiErr, err, "bar")
|
||||
|
||||
// TODO: Delete
|
||||
|
||||
// TODO: Error conditions once the proper errors are being returned.
|
||||
// Probably as parallel subtests against the same DB.
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
// Code generated by "make api"; DO NOT EDIT.
|
||||
package scopes
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/watchtower/api"
|
||||
)
|
||||
|
||||
func (s Organization) UpdateProject(ctx context.Context, project *Project) (*Project, *api.Error, error) {
|
||||
if s.Client == nil {
|
||||
return nil, nil, fmt.Errorf("nil client in CreateProject request")
|
||||
}
|
||||
if s.Id == "" {
|
||||
|
||||
// Assume the client has been configured with organization already and
|
||||
// move on
|
||||
|
||||
} else {
|
||||
// If it's explicitly set here, override anything that might be in the
|
||||
// client
|
||||
|
||||
ctx = context.WithValue(ctx, "org", s.Id)
|
||||
|
||||
}
|
||||
|
||||
id := project.Id
|
||||
project.Id = ""
|
||||
|
||||
req, err := s.Client.NewRequest(ctx, "PATCH", fmt.Sprintf("projects/%s", id), project)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error creating CreateProject request: %w", err)
|
||||
}
|
||||
|
||||
resp, err := s.Client.Do(req)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error performing client request during UpdateProject call: %w", err)
|
||||
}
|
||||
|
||||
target := new(Project)
|
||||
apiErr, err := resp.Decode(target)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error decoding UpdateProject repsonse: %w", err)
|
||||
}
|
||||
|
||||
target.Client = s.Client.Clone()
|
||||
target.Client.SetProject(target.Id)
|
||||
|
||||
return target, apiErr, nil
|
||||
}
|
||||
@@ -51,6 +51,7 @@ require (
|
||||
go.mongodb.org/mongo-driver v1.3.2 // indirect
|
||||
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f
|
||||
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1
|
||||
golang.org/x/tools v0.0.0-20200426102838-f3a5411a4c3b
|
||||
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380
|
||||
google.golang.org/grpc v1.29.1
|
||||
google.golang.org/protobuf v1.22.0
|
||||
|
||||
@@ -568,8 +568,6 @@ github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyN
|
||||
github.com/hashicorp/consul/sdk v0.2.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
||||
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-alpnmux v0.0.0-20200323180452-dee08f00df54 h1:WhMHPQosFuXFjt2wpRzX2eqR1WpnS+35MFzmG3trg3Y=
|
||||
github.com/hashicorp/go-alpnmux v0.0.0-20200323180452-dee08f00df54/go.mod h1:KvpteZzIafT4tRAuQ9vVRBgZyqeVCS2B2177fNAyEZc=
|
||||
github.com/hashicorp/go-alpnmux v0.0.0-20200513011953-0293f5d23c31 h1:pxqI71/0R1WIASjQEJ9W9skCKYiREEkRoXFvHCZH1pg=
|
||||
github.com/hashicorp/go-alpnmux v0.0.0-20200513011953-0293f5d23c31/go.mod h1:KvpteZzIafT4tRAuQ9vVRBgZyqeVCS2B2177fNAyEZc=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.21.0
|
||||
// protoc-gen-go v1.22.0
|
||||
// protoc v3.11.4
|
||||
// source: controller/storage/db/db_test/v1/db_test.proto
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.21.0
|
||||
// protoc-gen-go v1.22.0
|
||||
// protoc v3.11.4
|
||||
// source: controller/api/v1/error.proto
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.21.0
|
||||
// protoc-gen-go v1.22.0
|
||||
// protoc v3.11.4
|
||||
// source: controller/api/resources/hosts/v1/host.proto
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.21.0
|
||||
// protoc-gen-go v1.22.0
|
||||
// protoc v3.11.4
|
||||
// source: controller/api/resources/hosts/v1/host_catalog.proto
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.21.0
|
||||
// protoc-gen-go v1.22.0
|
||||
// protoc v3.11.4
|
||||
// source: controller/api/resources/hosts/v1/host_set.proto
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.21.0
|
||||
// protoc-gen-go v1.22.0
|
||||
// protoc v3.11.4
|
||||
// source: controller/api/resources/scopes/v1/organization.proto
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.21.0
|
||||
// protoc-gen-go v1.22.0
|
||||
// protoc v3.11.4
|
||||
// source: controller/api/resources/scopes/v1/project.proto
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.21.0
|
||||
// protoc-gen-go v1.22.0
|
||||
// protoc v3.11.4
|
||||
// source: controller/api/services/v1/host_catalog_service.proto
|
||||
|
||||
|
||||
@@ -135,7 +135,10 @@ func local_request_HostCatalogService_GetHostCatalog_0(ctx context.Context, mars
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
|
||||
}
|
||||
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_HostCatalogService_GetHostCatalog_0); err != nil {
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_HostCatalogService_GetHostCatalog_0); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
@@ -226,7 +229,10 @@ func local_request_HostCatalogService_GetHostCatalog_1(ctx context.Context, mars
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
|
||||
}
|
||||
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_HostCatalogService_GetHostCatalog_1); err != nil {
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_HostCatalogService_GetHostCatalog_1); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
@@ -317,7 +323,10 @@ func local_request_HostCatalogService_ListHostCatalogs_0(ctx context.Context, ma
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "project_id", err)
|
||||
}
|
||||
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_HostCatalogService_ListHostCatalogs_0); err != nil {
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_HostCatalogService_ListHostCatalogs_0); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
@@ -386,7 +395,10 @@ func local_request_HostCatalogService_ListHostCatalogs_1(ctx context.Context, ma
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "org_id", err)
|
||||
}
|
||||
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_HostCatalogService_ListHostCatalogs_1); err != nil {
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_HostCatalogService_ListHostCatalogs_1); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
@@ -563,7 +575,10 @@ func local_request_HostCatalogService_CreateHostCatalog_1(ctx context.Context, m
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "org_id", err)
|
||||
}
|
||||
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_HostCatalogService_CreateHostCatalog_1); err != nil {
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_HostCatalogService_CreateHostCatalog_1); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
@@ -708,7 +723,10 @@ func local_request_HostCatalogService_UpdateHostCatalog_0(ctx context.Context, m
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
|
||||
}
|
||||
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_HostCatalogService_UpdateHostCatalog_0); err != nil {
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_HostCatalogService_UpdateHostCatalog_0); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
@@ -831,7 +849,10 @@ func local_request_HostCatalogService_UpdateHostCatalog_1(ctx context.Context, m
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
|
||||
}
|
||||
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_HostCatalogService_UpdateHostCatalog_1); err != nil {
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_HostCatalogService_UpdateHostCatalog_1); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
@@ -1020,7 +1041,10 @@ func local_request_HostCatalogService_DeleteHostCatalog_1(ctx context.Context, m
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
|
||||
}
|
||||
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_HostCatalogService_DeleteHostCatalog_1); err != nil {
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_HostCatalogService_DeleteHostCatalog_1); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.21.0
|
||||
// protoc-gen-go v1.22.0
|
||||
// protoc v3.11.4
|
||||
// source: controller/api/services/v1/host_service.proto
|
||||
|
||||
|
||||
@@ -157,7 +157,10 @@ func local_request_HostService_GetHost_0(ctx context.Context, marshaler runtime.
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
|
||||
}
|
||||
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_HostService_GetHost_0); err != nil {
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_HostService_GetHost_0); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
@@ -270,7 +273,10 @@ func local_request_HostService_GetHost_1(ctx context.Context, marshaler runtime.
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
|
||||
}
|
||||
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_HostService_GetHost_1); err != nil {
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_HostService_GetHost_1); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
@@ -383,7 +389,10 @@ func local_request_HostService_ListHosts_0(ctx context.Context, marshaler runtim
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "host_catalog_id", err)
|
||||
}
|
||||
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_HostService_ListHosts_0); err != nil {
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_HostService_ListHosts_0); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
@@ -452,7 +461,10 @@ func local_request_HostService_ListHosts_1(ctx context.Context, marshaler runtim
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "org_id", err)
|
||||
}
|
||||
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_HostService_ListHosts_1); err != nil {
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_HostService_ListHosts_1); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
@@ -673,7 +685,10 @@ func local_request_HostService_CreateHost_1(ctx context.Context, marshaler runti
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "host_catalog_id", err)
|
||||
}
|
||||
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_HostService_CreateHost_1); err != nil {
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_HostService_CreateHost_1); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
@@ -840,7 +855,10 @@ func local_request_HostService_UpdateHost_0(ctx context.Context, marshaler runti
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
|
||||
}
|
||||
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_HostService_UpdateHost_0); err != nil {
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_HostService_UpdateHost_0); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
@@ -985,7 +1003,10 @@ func local_request_HostService_UpdateHost_1(ctx context.Context, marshaler runti
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
|
||||
}
|
||||
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_HostService_UpdateHost_1); err != nil {
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_HostService_UpdateHost_1); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
@@ -1218,7 +1239,10 @@ func local_request_HostService_DeleteHost_1(ctx context.Context, marshaler runti
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
|
||||
}
|
||||
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_HostService_DeleteHost_1); err != nil {
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_HostService_DeleteHost_1); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.21.0
|
||||
// protoc-gen-go v1.22.0
|
||||
// protoc v3.11.4
|
||||
// source: controller/api/services/v1/host_set_service.proto
|
||||
|
||||
|
||||
@@ -157,7 +157,10 @@ func local_request_HostSetService_GetHostSet_0(ctx context.Context, marshaler ru
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
|
||||
}
|
||||
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_HostSetService_GetHostSet_0); err != nil {
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_HostSetService_GetHostSet_0); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
@@ -270,7 +273,10 @@ func local_request_HostSetService_GetHostSet_1(ctx context.Context, marshaler ru
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
|
||||
}
|
||||
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_HostSetService_GetHostSet_1); err != nil {
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_HostSetService_GetHostSet_1); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
@@ -383,7 +389,10 @@ func local_request_HostSetService_ListHostSets_0(ctx context.Context, marshaler
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "host_catalog_id", err)
|
||||
}
|
||||
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_HostSetService_ListHostSets_0); err != nil {
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_HostSetService_ListHostSets_0); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
@@ -474,7 +483,10 @@ func local_request_HostSetService_ListHostSets_1(ctx context.Context, marshaler
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "host_catalog_id", err)
|
||||
}
|
||||
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_HostSetService_ListHostSets_1); err != nil {
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_HostSetService_ListHostSets_1); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
@@ -695,7 +707,10 @@ func local_request_HostSetService_CreateHostSet_1(ctx context.Context, marshaler
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "host_catalog_id", err)
|
||||
}
|
||||
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_HostSetService_CreateHostSet_1); err != nil {
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_HostSetService_CreateHostSet_1); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
@@ -862,7 +877,10 @@ func local_request_HostSetService_UpdateHostSet_0(ctx context.Context, marshaler
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
|
||||
}
|
||||
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_HostSetService_UpdateHostSet_0); err != nil {
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_HostSetService_UpdateHostSet_0); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
@@ -1007,7 +1025,10 @@ func local_request_HostSetService_UpdateHostSet_1(ctx context.Context, marshaler
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
|
||||
}
|
||||
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_HostSetService_UpdateHostSet_1); err != nil {
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_HostSetService_UpdateHostSet_1); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
@@ -1240,7 +1261,10 @@ func local_request_HostSetService_DeleteHostSet_1(ctx context.Context, marshaler
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
|
||||
}
|
||||
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_HostSetService_DeleteHostSet_1); err != nil {
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_HostSetService_DeleteHostSet_1); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
@@ -1375,7 +1399,10 @@ func local_request_HostSetService_AddToHostSet_0(ctx context.Context, marshaler
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
|
||||
}
|
||||
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_HostSetService_AddToHostSet_0); err != nil {
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_HostSetService_AddToHostSet_0); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
@@ -1488,7 +1515,10 @@ func local_request_HostSetService_AddToHostSet_1(ctx context.Context, marshaler
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
|
||||
}
|
||||
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_HostSetService_AddToHostSet_1); err != nil {
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_HostSetService_AddToHostSet_1); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
@@ -1623,7 +1653,10 @@ func local_request_HostSetService_RemoveFromHostSet_0(ctx context.Context, marsh
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
|
||||
}
|
||||
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_HostSetService_RemoveFromHostSet_0); err != nil {
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_HostSetService_RemoveFromHostSet_0); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
@@ -1736,7 +1769,10 @@ func local_request_HostSetService_RemoveFromHostSet_1(ctx context.Context, marsh
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
|
||||
}
|
||||
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_HostSetService_RemoveFromHostSet_1); err != nil {
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_HostSetService_RemoveFromHostSet_1); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.21.0
|
||||
// protoc-gen-go v1.22.0
|
||||
// protoc v3.11.4
|
||||
// source: controller/api/services/v1/project_service.proto
|
||||
|
||||
|
||||
@@ -113,7 +113,10 @@ func local_request_ProjectService_GetProject_0(ctx context.Context, marshaler ru
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
|
||||
}
|
||||
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_ProjectService_GetProject_0); err != nil {
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_ProjectService_GetProject_0); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
@@ -182,7 +185,10 @@ func local_request_ProjectService_ListProjects_0(ctx context.Context, marshaler
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "org_id", err)
|
||||
}
|
||||
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_ProjectService_ListProjects_0); err != nil {
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_ProjectService_ListProjects_0); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
@@ -375,7 +381,10 @@ func local_request_ProjectService_UpdateProject_0(ctx context.Context, marshaler
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
|
||||
}
|
||||
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_ProjectService_UpdateProject_0); err != nil {
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_ProjectService_UpdateProject_0); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.21.0
|
||||
// protoc-gen-go v1.22.0
|
||||
// protoc v3.11.4
|
||||
// source: controller/storage/v1/placeholder.proto
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.21.0
|
||||
// protoc-gen-go v1.22.0
|
||||
// protoc v3.11.4
|
||||
// source: controller/storage/iam/store/v1/scope.proto
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.21.0
|
||||
// protoc-gen-go v1.22.0
|
||||
// protoc v3.11.4
|
||||
// source: controller/storage/iam/store/v1/timestamp.proto
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.21.0
|
||||
// protoc-gen-go v1.22.0
|
||||
// protoc v3.11.4
|
||||
// source: controller/storage/oplog/v1/any_operation.proto
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.21.0
|
||||
// protoc-gen-go v1.22.0
|
||||
// protoc v3.11.4
|
||||
// source: controller/storage/oplog/test/v1/oplog_test.proto
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.21.0
|
||||
// protoc-gen-go v1.22.0
|
||||
// protoc v3.11.4
|
||||
// source: controller/storage/oplog/store/v1/oplog.proto
|
||||
|
||||
|
||||
@@ -11,11 +11,19 @@ import (
|
||||
pb "github.com/hashicorp/watchtower/internal/gen/controller/api/resources/scopes"
|
||||
pbs "github.com/hashicorp/watchtower/internal/gen/controller/api/services"
|
||||
"github.com/hashicorp/watchtower/internal/iam"
|
||||
"google.golang.org/genproto/protobuf/field_mask"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
var reInvalidID = regexp.MustCompile("[^A-Za-z0-9]")
|
||||
var (
|
||||
reInvalidID = regexp.MustCompile("[^A-Za-z0-9]")
|
||||
// TODO(ICU-28): Find a way to auto update these names and enforce the mappings between wire and storage.
|
||||
wireToStorageMask = map[string]string{
|
||||
"name": "Name",
|
||||
"description": "Description",
|
||||
}
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
pbs.UnimplementedProjectServiceServer
|
||||
@@ -107,22 +115,25 @@ func (s Service) createInRepo(ctx context.Context, req *pbs.CreateProjectRequest
|
||||
|
||||
func (s Service) updateInRepo(ctx context.Context, req *pbs.UpdateProjectRequest) (*pb.Project, error) {
|
||||
item := req.GetItem()
|
||||
// TODO: convert field masks from API field masks with snake_case to db field masks casing.
|
||||
madeUp := []string{}
|
||||
opts := []iam.Option{iam.WithPublicId(req.GetId())}
|
||||
if desc := item.GetDescription(); desc != nil {
|
||||
madeUp = append(madeUp, "Description")
|
||||
opts = append(opts, iam.WithDescription(desc.GetValue()))
|
||||
}
|
||||
if name := item.GetName(); name != nil {
|
||||
madeUp = append(madeUp, "Name")
|
||||
opts = append(opts, iam.WithName(name.GetValue()))
|
||||
}
|
||||
p, err := iam.NewProject(req.GetOrgId(), opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out, _, err := s.repo.UpdateScope(ctx, p, madeUp)
|
||||
dbMask, err := toDbUpdateMask(req.GetUpdateMask())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(dbMask) == 0 {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "No valid fields included in the update mask.")
|
||||
}
|
||||
out, _, err := s.repo.UpdateScope(ctx, p, dbMask)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -132,6 +143,25 @@ func (s Service) updateInRepo(ctx context.Context, req *pbs.UpdateProjectRequest
|
||||
return toProto(out), nil
|
||||
}
|
||||
|
||||
// toDbUpdateMask converts the wire format's FieldMask into a list of strings containing FieldMask paths used
|
||||
func toDbUpdateMask(fm *field_mask.FieldMask) ([]string, error) {
|
||||
dbPaths := []string{}
|
||||
invalid := []string{}
|
||||
for _, p := range fm.GetPaths() {
|
||||
for _, f := range strings.Split(p, ",") {
|
||||
if dbField, ok := wireToStorageMask[strings.TrimSpace(f)]; ok {
|
||||
dbPaths = append(dbPaths, dbField)
|
||||
} else {
|
||||
invalid = append(invalid, f)
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(invalid) > 0 {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "Invalid fields passed in update_update mask: %v", invalid)
|
||||
}
|
||||
return dbPaths, nil
|
||||
}
|
||||
|
||||
func toProto(in *iam.Scope) *pb.Project {
|
||||
out := pb.Project{Id: in.GetPublicId()}
|
||||
if in.GetDescription() != "" {
|
||||
@@ -194,7 +224,9 @@ func validateUpdateProjectRequest(req *pbs.UpdateProjectRequest) error {
|
||||
if err := validateID(req.GetOrgId(), "o_"); err != nil {
|
||||
return err
|
||||
}
|
||||
// TODO: Either require mask to be set or document in API that an unset mask updates all fields.
|
||||
if req.GetUpdateMask() == nil {
|
||||
return status.Errorf(codes.InvalidArgument, "UpdateMask not provided but is required to update a project.")
|
||||
}
|
||||
item := req.GetItem()
|
||||
if item == nil {
|
||||
// It is legitimate for no item to be specified in an update request as it indicates all fields provided in
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
pbs "github.com/hashicorp/watchtower/internal/gen/controller/api/services"
|
||||
"github.com/hashicorp/watchtower/internal/iam"
|
||||
"github.com/hashicorp/watchtower/internal/servers/controller/handlers/projects"
|
||||
"google.golang.org/genproto/protobuf/field_mask"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
@@ -42,7 +43,7 @@ func createDefaultProjectAndRepo(t *testing.T) (*iam.Scope, *iam.Repository) {
|
||||
t.Fatalf("Could not create org scope: %v", err)
|
||||
}
|
||||
|
||||
p, err := iam.NewProject(oRes.GetPublicId(), iam.WithName("default"))
|
||||
p, err := iam.NewProject(oRes.GetPublicId(), iam.WithName("default"), iam.WithDescription("default"))
|
||||
if err != nil {
|
||||
t.Fatalf("Could not get new project: %v", err)
|
||||
}
|
||||
@@ -64,6 +65,7 @@ func TestGet(t *testing.T) {
|
||||
pProject := &pb.Project{
|
||||
Id: proj.GetPublicId(),
|
||||
Name: &wrappers.StringValue{Value: proj.GetName()},
|
||||
Description: &wrappers.StringValue{Value: proj.GetDescription()},
|
||||
CreatedTime: proj.CreateTime.GetTimestamp(),
|
||||
UpdatedTime: proj.UpdateTime.GetTimestamp(),
|
||||
}
|
||||
@@ -210,6 +212,15 @@ func TestCreate(t *testing.T) {
|
||||
|
||||
func TestUpdate(t *testing.T) {
|
||||
proj, repo := createDefaultProjectAndRepo(t)
|
||||
tested := projects.NewService(repo)
|
||||
|
||||
var err error
|
||||
resetProject := func() {
|
||||
if proj, _, err = repo.UpdateScope(context.Background(), proj, []string{"Name", "Description"}); err != nil {
|
||||
t.Fatalf("Failed to reset the project")
|
||||
}
|
||||
}
|
||||
|
||||
projCreated, err := ptypes.Timestamp(proj.GetCreateTime().GetTimestamp())
|
||||
if err != nil {
|
||||
t.Fatalf("Error converting proto to timestamp: %v", err)
|
||||
@@ -227,10 +238,15 @@ func TestUpdate(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
name: "Update an Existing Project",
|
||||
req: &pbs.UpdateProjectRequest{Item: &pb.Project{
|
||||
Name: &wrappers.StringValue{Value: "new"},
|
||||
Description: &wrappers.StringValue{Value: "desc"},
|
||||
}},
|
||||
req: &pbs.UpdateProjectRequest{
|
||||
UpdateMask: &field_mask.FieldMask{
|
||||
Paths: []string{"name", "description"},
|
||||
},
|
||||
Item: &pb.Project{
|
||||
Name: &wrappers.StringValue{Value: "new"},
|
||||
Description: &wrappers.StringValue{Value: "desc"},
|
||||
},
|
||||
},
|
||||
res: &pbs.UpdateProjectResponse{
|
||||
Item: &pb.Project{
|
||||
Id: proj.GetPublicId(),
|
||||
@@ -242,23 +258,142 @@ func TestUpdate(t *testing.T) {
|
||||
errCode: codes.OK,
|
||||
},
|
||||
{
|
||||
name: "Update a Non Existing Project",
|
||||
name: "Multiple Paths in single string",
|
||||
req: &pbs.UpdateProjectRequest{
|
||||
Id: "p_DoesntExis",
|
||||
UpdateMask: &field_mask.FieldMask{
|
||||
Paths: []string{"name,description"},
|
||||
},
|
||||
Item: &pb.Project{
|
||||
Name: &wrappers.StringValue{Value: "new"},
|
||||
Description: &wrappers.StringValue{Value: "desc"},
|
||||
},
|
||||
},
|
||||
res: &pbs.UpdateProjectResponse{
|
||||
Item: &pb.Project{
|
||||
Id: proj.GetPublicId(),
|
||||
Name: &wrappers.StringValue{Value: "new"},
|
||||
Description: &wrappers.StringValue{Value: "desc"},
|
||||
CreatedTime: proj.GetCreateTime().GetTimestamp(),
|
||||
},
|
||||
},
|
||||
errCode: codes.OK,
|
||||
},
|
||||
{
|
||||
name: "No Update Mask Is Invalid Argument",
|
||||
req: &pbs.UpdateProjectRequest{
|
||||
Item: &pb.Project{
|
||||
Name: &wrappers.StringValue{Value: "updated name"},
|
||||
Description: &wrappers.StringValue{Value: "updated desc"},
|
||||
},
|
||||
},
|
||||
errCode: codes.InvalidArgument,
|
||||
},
|
||||
{
|
||||
name: "No Paths in Mask Is Invalid Argument",
|
||||
req: &pbs.UpdateProjectRequest{
|
||||
UpdateMask: &field_mask.FieldMask{Paths: []string{}},
|
||||
Item: &pb.Project{
|
||||
Name: &wrappers.StringValue{Value: "updated name"},
|
||||
Description: &wrappers.StringValue{Value: "updated desc"},
|
||||
},
|
||||
},
|
||||
errCode: codes.InvalidArgument,
|
||||
},
|
||||
{
|
||||
name: "Only non-existant paths in Mask Is Invalid Argument",
|
||||
req: &pbs.UpdateProjectRequest{
|
||||
UpdateMask: &field_mask.FieldMask{Paths: []string{"nonexistant_field"}},
|
||||
Item: &pb.Project{
|
||||
Name: &wrappers.StringValue{Value: "updated name"},
|
||||
Description: &wrappers.StringValue{Value: "updated desc"},
|
||||
},
|
||||
},
|
||||
errCode: codes.InvalidArgument,
|
||||
},
|
||||
{
|
||||
name: "Unset Name",
|
||||
req: &pbs.UpdateProjectRequest{
|
||||
UpdateMask: &field_mask.FieldMask{
|
||||
Paths: []string{"name"},
|
||||
},
|
||||
Item: &pb.Project{
|
||||
Description: &wrappers.StringValue{Value: "ignored"},
|
||||
},
|
||||
},
|
||||
res: &pbs.UpdateProjectResponse{
|
||||
Item: &pb.Project{
|
||||
Id: proj.GetPublicId(),
|
||||
Description: &wrappers.StringValue{Value: "default"},
|
||||
CreatedTime: proj.GetCreateTime().GetTimestamp(),
|
||||
},
|
||||
},
|
||||
errCode: codes.OK,
|
||||
},
|
||||
{
|
||||
name: "Update Only Name",
|
||||
req: &pbs.UpdateProjectRequest{
|
||||
UpdateMask: &field_mask.FieldMask{
|
||||
Paths: []string{"name"},
|
||||
},
|
||||
Item: &pb.Project{
|
||||
Name: &wrappers.StringValue{Value: "updated"},
|
||||
Description: &wrappers.StringValue{Value: "ignored"},
|
||||
},
|
||||
},
|
||||
res: &pbs.UpdateProjectResponse{
|
||||
Item: &pb.Project{
|
||||
Id: proj.GetPublicId(),
|
||||
Name: &wrappers.StringValue{Value: "updated"},
|
||||
Description: &wrappers.StringValue{Value: "default"},
|
||||
CreatedTime: proj.GetCreateTime().GetTimestamp(),
|
||||
},
|
||||
},
|
||||
errCode: codes.OK,
|
||||
},
|
||||
{
|
||||
name: "Update Only Description",
|
||||
req: &pbs.UpdateProjectRequest{
|
||||
UpdateMask: &field_mask.FieldMask{
|
||||
Paths: []string{"description"},
|
||||
},
|
||||
Item: &pb.Project{
|
||||
Name: &wrappers.StringValue{Value: "ignored"},
|
||||
Description: &wrappers.StringValue{Value: "notignored"},
|
||||
},
|
||||
},
|
||||
res: &pbs.UpdateProjectResponse{
|
||||
Item: &pb.Project{
|
||||
Id: proj.GetPublicId(),
|
||||
Name: &wrappers.StringValue{Value: "default"},
|
||||
Description: &wrappers.StringValue{Value: "notignored"},
|
||||
CreatedTime: proj.GetCreateTime().GetTimestamp(),
|
||||
},
|
||||
},
|
||||
errCode: codes.OK,
|
||||
},
|
||||
{
|
||||
name: "Update a Non Existing Project",
|
||||
req: &pbs.UpdateProjectRequest{
|
||||
Id: "p_DoesntExis",
|
||||
UpdateMask: &field_mask.FieldMask{
|
||||
Paths: []string{"description"},
|
||||
},
|
||||
Item: &pb.Project{
|
||||
Name: &wrappers.StringValue{Value: "new"},
|
||||
Description: &wrappers.StringValue{Value: "desc"},
|
||||
},
|
||||
},
|
||||
// TODO: Update this to be NotFound.
|
||||
errCode: codes.Unknown,
|
||||
},
|
||||
{
|
||||
name: "Cant change Id",
|
||||
req: &pbs.UpdateProjectRequest{
|
||||
Id: "p_1234567890",
|
||||
Id: proj.GetPublicId(),
|
||||
UpdateMask: &field_mask.FieldMask{
|
||||
Paths: []string{"id"},
|
||||
},
|
||||
Item: &pb.Project{
|
||||
Id: "p_0987654321",
|
||||
Id: "p_somethinge",
|
||||
Name: &wrappers.StringValue{Value: "new"},
|
||||
Description: &wrappers.StringValue{Value: "new desc"},
|
||||
}},
|
||||
@@ -267,33 +402,43 @@ func TestUpdate(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "Cant specify Created Time",
|
||||
req: &pbs.UpdateProjectRequest{Item: &pb.Project{
|
||||
CreatedTime: ptypes.TimestampNow(),
|
||||
}},
|
||||
req: &pbs.UpdateProjectRequest{
|
||||
UpdateMask: &field_mask.FieldMask{
|
||||
Paths: []string{"created_time"},
|
||||
},
|
||||
Item: &pb.Project{
|
||||
CreatedTime: ptypes.TimestampNow(),
|
||||
},
|
||||
},
|
||||
res: nil,
|
||||
errCode: codes.InvalidArgument,
|
||||
},
|
||||
{
|
||||
name: "Cant specify Updated Time",
|
||||
req: &pbs.UpdateProjectRequest{Item: &pb.Project{
|
||||
UpdatedTime: ptypes.TimestampNow(),
|
||||
}},
|
||||
req: &pbs.UpdateProjectRequest{
|
||||
UpdateMask: &field_mask.FieldMask{
|
||||
Paths: []string{"updated_time"},
|
||||
},
|
||||
Item: &pb.Project{
|
||||
UpdatedTime: ptypes.TimestampNow(),
|
||||
},
|
||||
},
|
||||
res: nil,
|
||||
errCode: codes.InvalidArgument,
|
||||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
defer resetProject()
|
||||
assert := assert.New(t)
|
||||
req := proto.Clone(toMerge).(*pbs.UpdateProjectRequest)
|
||||
proto.Merge(req, tc.req)
|
||||
|
||||
s := projects.NewService(repo)
|
||||
|
||||
got, gErr := s.UpdateProject(context.Background(), req)
|
||||
got, gErr := tested.UpdateProject(context.Background(), req)
|
||||
assert.Equal(tc.errCode, status.Code(gErr), "UpdateProject(%+v) got error %v, wanted %v", req, gErr, tc.errCode)
|
||||
|
||||
if got != nil {
|
||||
assert.NotNilf(tc.res, "Expected UpdateProject response to be nil, but was %v", got)
|
||||
gotUpdateTime, err := ptypes.Timestamp(got.GetItem().GetUpdatedTime())
|
||||
if err != nil {
|
||||
t.Fatalf("Error converting proto to timestamp: %v", err)
|
||||
@@ -305,7 +450,7 @@ func TestUpdate(t *testing.T) {
|
||||
_ = projCreated
|
||||
|
||||
// Clear all values which are hard to compare against.
|
||||
got.Item.CreatedTime, got.Item.UpdatedTime, tc.res.Item.CreatedTime, tc.res.Item.UpdatedTime = nil, nil, nil, nil
|
||||
got.Item.UpdatedTime, tc.res.Item.UpdatedTime = nil, nil
|
||||
}
|
||||
assert.True(proto.Equal(got, tc.res), "UpdateProject(%q) got response %q, wanted %q", req, got, tc.res)
|
||||
})
|
||||
|
||||
+20
-15
@@ -10,23 +10,28 @@
|
||||
|
||||
package tools
|
||||
|
||||
//go:generate go install github.com/bufbuild/buf/cmd/buf
|
||||
import _ "github.com/bufbuild/buf/cmd/buf"
|
||||
import (
|
||||
//go:generate go install github.com/bufbuild/buf/cmd/buf
|
||||
_ "github.com/bufbuild/buf/cmd/buf"
|
||||
|
||||
//go:generate go install github.com/go-swagger/go-swagger/cmd/swagger
|
||||
import _ "github.com/go-swagger/go-swagger/cmd/swagger"
|
||||
//go:generate go install github.com/favadi/protoc-go-inject-tag
|
||||
_ "github.com/favadi/protoc-go-inject-tag"
|
||||
|
||||
//go:generate go install github.com/favadi/protoc-go-inject-tag
|
||||
import _ "github.com/favadi/protoc-go-inject-tag"
|
||||
//go:generate go install github.com/go-swagger/go-swagger/cmd/swagger
|
||||
_ "github.com/go-swagger/go-swagger/cmd/swagger"
|
||||
|
||||
// use this instead of google.golang.org/protobuf/cmd/protoc-gen-go since this supports grpc plugin while the other does not.
|
||||
// see https://github.com/golang/protobuf/releases#v1.4-generated-code and
|
||||
// https://github.com/protocolbuffers/protobuf-go/releases/tag/v1.20.0#v1.20-grpc-support
|
||||
//go:generate go install github.com/golang/protobuf/protoc-gen-go
|
||||
import _ "github.com/golang/protobuf/protoc-gen-go"
|
||||
// use this instead of google.golang.org/protobuf/cmd/protoc-gen-go since this supports grpc plugin while the other does not.
|
||||
// see https://github.com/golang/protobuf/releases#v1.4-generated-code and
|
||||
// https://github.com/protocolbuffers/protobuf-go/releases/tag/v1.20.0#v1.20-grpc-support
|
||||
//go:generate go install github.com/golang/protobuf/protoc-gen-go
|
||||
_ "github.com/golang/protobuf/protoc-gen-go"
|
||||
|
||||
//go:generate go install github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway
|
||||
import _ "github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway"
|
||||
//go:generate go install github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway
|
||||
_ "github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway"
|
||||
|
||||
//go:generate go install github.com/grpc-ecosystem/grpc-gateway/protoc-gen-swagger
|
||||
import _ "github.com/grpc-ecosystem/grpc-gateway/protoc-gen-swagger"
|
||||
//go:generate go install github.com/grpc-ecosystem/grpc-gateway/protoc-gen-swagger
|
||||
_ "github.com/grpc-ecosystem/grpc-gateway/protoc-gen-swagger"
|
||||
|
||||
//go:generate go install golang.org/x/tools/cmd/goimports
|
||||
_ "golang.org/x/tools/cmd/goimports"
|
||||
)
|
||||
Reference in new issue
Block a user