Xw/net 5724 grpc client delete (#20309)

* delete commmand works
This commit is contained in:
wangxinyi7 2024-01-24 15:17:54 -08:00 committed by GitHub
parent 6828780131
commit 7bb2c7cf13
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
22 changed files with 442 additions and 85 deletions

View File

@ -233,7 +233,7 @@ COPY LICENSE /licenses/mozilla.txt
# Set up certificates and base tools. # Set up certificates and base tools.
# dumb-init is downloaded directly from GitHub because there's no RPM package. # dumb-init is downloaded directly from GitHub because there's no RPM package.
# Its shasum is hardcoded. If you upgrade the dumb-init verion you'll need to # Its shasum is hardcoded. If you upgrade the dumb-init version you'll need to
# also update the shasum. # also update the shasum.
RUN set -eux && \ RUN set -eux && \
microdnf install -y ca-certificates shadow-utils gnupg libcap openssl iputils jq iptables wget unzip tar && \ microdnf install -y ca-certificates shadow-utils gnupg libcap openssl iputils jq iptables wget unzip tar && \

View File

@ -117,6 +117,7 @@ import (
resourceapply "github.com/hashicorp/consul/command/resource/apply" resourceapply "github.com/hashicorp/consul/command/resource/apply"
resourceapplygrpc "github.com/hashicorp/consul/command/resource/apply-grpc" resourceapplygrpc "github.com/hashicorp/consul/command/resource/apply-grpc"
resourcedelete "github.com/hashicorp/consul/command/resource/delete" resourcedelete "github.com/hashicorp/consul/command/resource/delete"
resourcedeletegrpc "github.com/hashicorp/consul/command/resource/delete-grpc"
resourcelist "github.com/hashicorp/consul/command/resource/list" resourcelist "github.com/hashicorp/consul/command/resource/list"
resourcelistgrpc "github.com/hashicorp/consul/command/resource/list-grpc" resourcelistgrpc "github.com/hashicorp/consul/command/resource/list-grpc"
resourceread "github.com/hashicorp/consul/command/resource/read" resourceread "github.com/hashicorp/consul/command/resource/read"
@ -265,6 +266,7 @@ func RegisteredCommands(ui cli.Ui) map[string]mcli.CommandFactory {
entry{"resource apply-grpc", func(ui cli.Ui) (cli.Command, error) { return resourceapplygrpc.New(ui), nil }}, entry{"resource apply-grpc", func(ui cli.Ui) (cli.Command, error) { return resourceapplygrpc.New(ui), nil }},
entry{"resource read-grpc", func(ui cli.Ui) (cli.Command, error) { return resourcereadgrpc.New(ui), nil }}, entry{"resource read-grpc", func(ui cli.Ui) (cli.Command, error) { return resourcereadgrpc.New(ui), nil }},
entry{"resource list-grpc", func(ui cli.Ui) (cli.Command, error) { return resourcelistgrpc.New(ui), nil }}, entry{"resource list-grpc", func(ui cli.Ui) (cli.Command, error) { return resourcelistgrpc.New(ui), nil }},
entry{"resource delete-grpc", func(ui cli.Ui) (cli.Command, error) { return resourcedeletegrpc.New(ui), nil }},
entry{"resource list", func(ui cli.Ui) (cli.Command, error) { return resourcelist.New(ui), nil }}, entry{"resource list", func(ui cli.Ui) (cli.Command, error) { return resourcelist.New(ui), nil }},
entry{"rtt", func(ui cli.Ui) (cli.Command, error) { return rtt.New(ui), nil }}, entry{"rtt", func(ui cli.Ui) (cli.Command, error) { return rtt.New(ui), nil }},
entry{"services", func(cli.Ui) (cli.Command, error) { return services.New(), nil }}, entry{"services", func(cli.Ui) (cli.Command, error) { return services.New(), nil }},

View File

@ -134,8 +134,8 @@ Usage: consul resource apply [options] <resource>
Type = gvk("group.version.kind") Type = gvk("group.version.kind")
Name = "resource-name" Name = "resource-name"
Tenancy { Tenancy {
Namespace = "default"
Partition = "default" Partition = "default"
Namespace = "default"
PeerName = "local" PeerName = "local"
} }
} }

View File

@ -94,8 +94,8 @@ func TestResourceApplyCommand_StdIn(t *testing.T) {
Type = gvk("demo.v2.Artist") Type = gvk("demo.v2.Artist")
Name = "korn" Name = "korn"
Tenancy { Tenancy {
Namespace = "default"
Partition = "default" Partition = "default"
Namespace = "default"
PeerName = "local" PeerName = "local"
} }
} }
@ -145,8 +145,8 @@ func TestResourceApplyCommand_StdIn(t *testing.T) {
"id": { "id": {
"name": "korn", "name": "korn",
"tenancy": { "tenancy": {
"namespace": "default",
"partition": "default", "partition": "default",
"namespace": "default",
"peerName": "local" "peerName": "local"
}, },
"type": { "type": {

View File

@ -6,21 +6,21 @@ package client
import "flag" import "flag"
type ResourceFlags struct { type ResourceFlags struct {
namespace TValue[string]
partition TValue[string] partition TValue[string]
namespace TValue[string]
peername TValue[string] peername TValue[string]
stale TValue[bool] stale TValue[bool]
} }
func (f *ResourceFlags) ResourceFlags() *flag.FlagSet { func (f *ResourceFlags) ResourceFlags() *flag.FlagSet {
fs := flag.NewFlagSet("", flag.ContinueOnError) fs := flag.NewFlagSet("", flag.ContinueOnError)
fs.Var(&f.namespace, "namespace",
"Specifies the namespace to query. If not provided, the namespace will be inferred "+
"from the request's ACL token, or will default to the `default` namespace.")
fs.Var(&f.partition, "partition", fs.Var(&f.partition, "partition",
"Specifies the admin partition to query. If not provided, the admin partition will be inferred "+ "Specifies the admin partition to query. If not provided, the admin partition will be inferred "+
"from the request's ACL token, or will default to the `default` admin partition. "+ "from the request's ACL token, or will default to the `default` admin partition. "+
"Admin Partitions are a Consul Enterprise feature.") "Admin Partitions are a Consul Enterprise feature.")
fs.Var(&f.namespace, "namespace",
"Specifies the namespace to query. If not provided, the namespace will be inferred "+
"from the request's ACL token, or will default to the `default` namespace.")
fs.Var(&f.peername, "peer", "Specifies the name of peer to query. By default, it is `local`.") fs.Var(&f.peername, "peer", "Specifies the name of peer to query. By default, it is `local`.")
fs.Var(&f.stale, "stale", fs.Var(&f.stale, "stale",
"Permit any Consul server (non-leader) to respond to this request. This "+ "Permit any Consul server (non-leader) to respond to this request. This "+
@ -30,14 +30,14 @@ func (f *ResourceFlags) ResourceFlags() *flag.FlagSet {
return fs return fs
} }
func (f *ResourceFlags) Namespace() string {
return f.namespace.String()
}
func (f *ResourceFlags) Partition() string { func (f *ResourceFlags) Partition() string {
return f.partition.String() return f.partition.String()
} }
func (f *ResourceFlags) Namespace() string {
return f.namespace.String()
}
func (f *ResourceFlags) Peername() string { func (f *ResourceFlags) Peername() string {
return f.peername.String() return f.peername.String()
} }

View File

@ -0,0 +1,164 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package delete
import (
"errors"
"flag"
"fmt"
"github.com/mitchellh/cli"
"github.com/hashicorp/consul/command/flags"
"github.com/hashicorp/consul/command/resource"
"github.com/hashicorp/consul/command/resource/client"
"github.com/hashicorp/consul/proto-public/pbresource"
)
func New(ui cli.Ui) *cmd {
c := &cmd{UI: ui}
c.init()
return c
}
type cmd struct {
UI cli.Ui
flags *flag.FlagSet
grpcFlags *client.GRPCFlags
resourceFlags *client.ResourceFlags
help string
filePath string
}
func (c *cmd) init() {
c.flags = flag.NewFlagSet("", flag.ContinueOnError)
c.flags.StringVar(&c.filePath, "f", "",
"File path with resource definition")
c.grpcFlags = &client.GRPCFlags{}
c.resourceFlags = &client.ResourceFlags{}
client.MergeFlags(c.flags, c.grpcFlags.ClientFlags())
client.MergeFlags(c.flags, c.resourceFlags.ResourceFlags())
c.help = client.Usage(help, c.flags)
}
func (c *cmd) Run(args []string) int {
var resourceType *pbresource.Type
var resourceTenancy *pbresource.Tenancy
var resourceName string
if err := c.flags.Parse(args); err != nil {
if !errors.Is(err, flag.ErrHelp) {
c.UI.Error(fmt.Sprintf("Failed to parse args: %v", err))
return 1
}
c.UI.Error(fmt.Sprintf("Failed to run delete command: %v", err))
return 1
}
// collect resource type, name and tenancy
if c.flags.Lookup("f").Value.String() != "" {
if c.filePath == "" {
c.UI.Error(fmt.Sprintf("Please provide an input file with resource definition"))
return 1
}
parsedResource, err := resource.ParseResourceFromFile(c.filePath)
if err != nil {
c.UI.Error(fmt.Sprintf("Failed to decode resource from input file: %v", err))
return 1
}
if parsedResource == nil {
c.UI.Error("Unable to parse the file argument")
return 1
}
resourceType = parsedResource.Id.Type
resourceTenancy = parsedResource.Id.Tenancy
resourceName = parsedResource.Id.Name
} else {
var err error
resourceType, resourceName, err = resource.GetTypeAndResourceName(args)
if err != nil {
c.UI.Error(fmt.Sprintf("Incorrect argument format: %s", err))
return 1
}
inputArgs := args[2:]
err = resource.ParseInputParams(inputArgs, c.flags)
if err != nil {
c.UI.Error(fmt.Sprintf("Error parsing input arguments: %v", err))
return 1
}
if c.filePath != "" {
c.UI.Error("Incorrect argument format: File argument is not needed when resource information is provided with the command")
return 1
}
resourceTenancy = &pbresource.Tenancy{
Partition: c.resourceFlags.Partition(),
Namespace: c.resourceFlags.Namespace(),
PeerName: c.resourceFlags.Peername(),
}
}
// initialize client
config, err := client.LoadGRPCConfig(nil)
if err != nil {
c.UI.Error(fmt.Sprintf("Error loading config: %s", err))
return 1
}
c.grpcFlags.MergeFlagsIntoGRPCConfig(config)
resourceClient, err := client.NewGRPCClient(config)
if err != nil {
c.UI.Error(fmt.Sprintf("Error connect to Consul agent: %s", err))
return 1
}
// delete resource
res := resource.ResourceGRPC{C: resourceClient}
err = res.Delete(resourceType, resourceTenancy, resourceName)
if err != nil {
c.UI.Error(fmt.Sprintf("Error deleting resource %s/%s: %v", resourceType, resourceName, err))
return 1
}
c.UI.Info(fmt.Sprintf("%s.%s.%s/%s deleted", resourceType.Group, resourceType.GroupVersion, resourceType.Kind, resourceName))
return 0
}
func (c *cmd) Synopsis() string {
return synopsis
}
func (c *cmd) Help() string {
return flags.Usage(c.help, nil)
}
const synopsis = "Delete resource information"
const help = `
Usage: You have two options to delete the resource specified by the given
type, name, partition, namespace and peer and outputs its JSON representation.
consul resource delete [type] [name] -partition=<default> -namespace=<default> -peer=<local>
consul resource delete -f [resource_file_path]
But you could only use one of the approaches.
Example:
$ consul resource delete catalog.v2beta1.Service card-processor -partition=billing -namespace=payments -peer=eu
$ consul resource delete -f resource.hcl
In resource.hcl, it could be:
ID {
Type = gvk("catalog.v2beta1.Service")
Name = "card-processor"
Tenancy {
Partition = "billing"
Namespace = "payments"
PeerName = "eu"
}
}
`

View File

@ -0,0 +1,164 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package delete
import (
"errors"
"fmt"
"testing"
"github.com/mitchellh/cli"
"github.com/stretchr/testify/require"
"github.com/hashicorp/consul/agent"
"github.com/hashicorp/consul/command/resource/apply-grpc"
"github.com/hashicorp/consul/sdk/freeport"
"github.com/hashicorp/consul/testrpc"
)
func TestResourceDeleteInvalidArgs(t *testing.T) {
t.Parallel()
type tc struct {
args []string
expectedCode int
expectedErr error
}
cases := map[string]tc{
"nil args": {
args: nil,
expectedCode: 1,
expectedErr: errors.New("Incorrect argument format: Must specify two arguments: resource type and resource name"),
},
"empty args": {
args: []string{},
expectedCode: 1,
expectedErr: errors.New("Incorrect argument format: Must specify two arguments: resource type and resource name"),
},
"missing file path": {
args: []string{"-f"},
expectedCode: 1,
expectedErr: errors.New("Failed to parse args: flag needs an argument: -f"),
},
"file not found": {
args: []string{"-f=../testdata/test.hcl"},
expectedCode: 1,
expectedErr: errors.New("Failed to load data: Failed to read file: open ../testdata/test.hcl: no such file or directory"),
},
"provide type and name": {
args: []string{"a.b.c"},
expectedCode: 1,
expectedErr: errors.New("Incorrect argument format: Must specify two arguments: resource type and resource name"),
},
"provide type and name with -f": {
args: []string{"a.b.c", "name", "-f", "test.hcl"},
expectedCode: 1,
expectedErr: errors.New("Incorrect argument format: File argument is not needed when resource information is provided with the command"),
},
"provide type and name with -f and other flags": {
args: []string{"a.b.c", "name", "-f", "test.hcl", "-namespace", "default"},
expectedCode: 1,
expectedErr: errors.New("Incorrect argument format: File argument is not needed when resource information is provided with the command"),
},
"does not provide resource name after type": {
args: []string{"a.b.c", "-namespace", "default"},
expectedCode: 1,
expectedErr: errors.New("Incorrect argument format: Must provide resource name right after type"),
},
"invalid resource type format": {
args: []string{"a.", "name", "-namespace", "default"},
expectedCode: 1,
expectedErr: errors.New("Must provide resource type argument with either in group.version.kind format or its shorthand name"),
},
}
for desc, tc := range cases {
t.Run(desc, func(t *testing.T) {
ui := cli.NewMockUi()
c := New(ui)
code := c.Run(tc.args)
require.Equal(t, tc.expectedCode, code)
require.Contains(t, ui.ErrorWriter.String(), tc.expectedErr.Error())
})
}
}
func createResource(t *testing.T, port int) {
applyUi := cli.NewMockUi()
applyCmd := apply.New(applyUi)
args := []string{
fmt.Sprintf("-grpc-addr=127.0.0.1:%d", port),
"-token=root",
}
args = append(args, []string{"-f=../testdata/demo.hcl"}...)
code := applyCmd.Run(args)
require.Equal(t, 0, code)
require.Empty(t, applyUi.ErrorWriter.String())
}
func TestResourceDelete(t *testing.T) {
if testing.Short() {
t.Skip("too slow for testing.Short")
}
t.Parallel()
availablePort := freeport.GetOne(t)
a := agent.NewTestAgent(t, fmt.Sprintf("ports { grpc = %d }", availablePort))
testrpc.WaitForTestAgent(t, a.RPC, "dc1")
t.Cleanup(func() {
a.Shutdown()
})
defaultCmdArgs := []string{
fmt.Sprintf("-grpc-addr=127.0.0.1:%d", availablePort),
"-token=root",
}
cases := []struct {
name string
args []string
expectedCode int
createResource bool
}{
{
name: "delete resource in hcl format",
args: []string{"-f=../testdata/demo.hcl"},
expectedCode: 0,
createResource: true,
},
{
name: "delete resource in command line format",
args: []string{"demo.v2.Artist", "korn", "-partition=default", "-namespace=default", "-peer=local"},
expectedCode: 0,
createResource: true,
},
{
name: "delete resource that doesn't exist in command line format",
args: []string{"demo.v2.Artist", "korn", "-partition=default", "-namespace=default", "-peer=local"},
expectedCode: 0,
createResource: false,
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
ui := cli.NewMockUi()
c := New(ui)
cliArgs := append(tc.args, defaultCmdArgs...)
if tc.createResource {
createResource(t, availablePort)
}
code := c.Run(cliArgs)
require.Empty(t, ui.ErrorWriter.String())
require.Equal(t, tc.expectedCode, code)
require.Contains(t, ui.OutputWriter.String(), "deleted")
})
}
}

View File

@ -161,12 +161,12 @@ $ consul resource delete -f resource.hcl
In resource.hcl, it could be: In resource.hcl, it could be:
ID { ID {
Type = gvk("catalog.v2beta1.Service") Type = gvk("catalog.v2beta1.Service")
Name = "card-processor" Name = "card-processor"
Tenancy { Tenancy {
Namespace = "payments" Namespace = "payments"
Partition = "billing" Partition = "billing"
PeerName = "eu" PeerName = "eu"
} }
} }
` `

View File

@ -67,7 +67,7 @@ func TestResourceDeleteInvalidArgs(t *testing.T) {
"invalid resource type format": { "invalid resource type format": {
args: []string{"a.", "name", "-namespace", "default"}, args: []string{"a.", "name", "-namespace", "default"},
expectedCode: 1, expectedCode: 1,
expectedErr: errors.New("Must provide resource type argument with either in group.verion.kind format or its shorthand name"), expectedErr: errors.New("Must provide resource type argument with either in group.version.kind format or its shorthand name"),
}, },
} }

View File

@ -36,8 +36,8 @@ type OuterResource struct {
} }
type Tenancy struct { type Tenancy struct {
Namespace string `json:"namespace"`
Partition string `json:"partition"` Partition string `json:"partition"`
Namespace string `json:"namespace"`
PeerName string `json:"peerName"` PeerName string `json:"peerName"`
} }
@ -300,7 +300,7 @@ func InferTypeFromResourceType(resourceType string) (*pbresource.Type, error) {
Kind: s[2], Kind: s[2],
}, nil }, nil
default: default:
return nil, fmt.Errorf("Must provide resource type argument with either in group.verion.kind format or its shorthand name") return nil, fmt.Errorf("Must provide resource type argument with either in group.version.kind format or its shorthand name")
} }
} }

View File

@ -106,8 +106,8 @@ func (c *cmd) Run(args []string) int {
return 1 return 1
} }
resourceTenancy = &pbresource.Tenancy{ resourceTenancy = &pbresource.Tenancy{
Namespace: c.resourceFlags.Namespace(),
Partition: c.resourceFlags.Partition(), Partition: c.resourceFlags.Partition(),
Namespace: c.resourceFlags.Namespace(),
PeerName: c.resourceFlags.Peername(), PeerName: c.resourceFlags.Peername(),
} }
} }
@ -185,8 +185,8 @@ Sample demo.hcl:
ID { ID {
Type = gvk("group.version.kind") Type = gvk("group.version.kind")
Tenancy { Tenancy {
Namespace = "default"
Partition = "default" Partition = "default"
Namespace = "default"
PeerName = "local" PeerName = "local"
} }
} }

View File

@ -54,9 +54,9 @@ func TestResourceListCommand(t *testing.T) {
output: "\"name\": \"korn\"", output: "\"name\": \"korn\"",
extraArgs: []string{ extraArgs: []string{
"demo.v2.Artist", "demo.v2.Artist",
"-partition=default",
"-namespace=default", "-namespace=default",
"-peer=local", "-peer=local",
"-partition=default",
}, },
}, },
{ {
@ -65,9 +65,9 @@ func TestResourceListCommand(t *testing.T) {
extraArgs: []string{ extraArgs: []string{
"demo.v2.Artist", "demo.v2.Artist",
"-p=korn", "-p=korn",
"-partition=default",
"-namespace=default", "-namespace=default",
"-peer=local", "-peer=local",
"-partition=default",
}, },
}, },
{ {
@ -150,9 +150,9 @@ func TestResourceListInvalidArgs(t *testing.T) {
"file argument with resource type": { "file argument with resource type": {
args: []string{ args: []string{
"demo.v2.Artist", "demo.v2.Artist",
"-partition=default",
"-namespace=default", "-namespace=default",
"-peer=local", "-peer=local",
"-partition=default",
fmt.Sprintf("-grpc-addr=127.0.0.1:%d", availablePort), fmt.Sprintf("-grpc-addr=127.0.0.1:%d", availablePort),
"-token=root", "-token=root",
"-f=demo.hcl", "-f=demo.hcl",
@ -163,9 +163,9 @@ func TestResourceListInvalidArgs(t *testing.T) {
"resource type invalid": { "resource type invalid": {
args: []string{ args: []string{
"test", "test",
"-partition=default",
"-namespace=default", "-namespace=default",
"-peer=local", "-peer=local",
"-partition=default",
}, },
expectedCode: 1, expectedCode: 1,
expectedErr: errors.New("Incorrect argument format: The shorthand name does not map to any existing resource type"), expectedErr: errors.New("Incorrect argument format: The shorthand name does not map to any existing resource type"),

View File

@ -151,7 +151,7 @@ func getResourceType(args []string) (gvk *resource.GVK, e error) {
s := strings.Split(args[0], ".") s := strings.Split(args[0], ".")
if len(s) < 3 { if len(s) < 3 {
return nil, fmt.Errorf("Must include resource type argument in group.verion.kind format") return nil, fmt.Errorf("Must include resource type argument in group.version.kind format")
} }
gvk = &resource.GVK{ gvk = &resource.GVK{
Group: s[0], Group: s[0],

View File

@ -7,13 +7,14 @@ import (
"errors" "errors"
"testing" "testing"
"github.com/mitchellh/cli"
"github.com/hashicorp/consul/agent" "github.com/hashicorp/consul/agent"
"github.com/hashicorp/consul/testrpc" "github.com/hashicorp/consul/testrpc"
"github.com/mitchellh/cli"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
apply "github.com/hashicorp/consul/command/resource/apply" "github.com/hashicorp/consul/command/resource/apply"
) )
func TestResourceListCommand(t *testing.T) { func TestResourceListCommand(t *testing.T) {
@ -148,7 +149,7 @@ func TestResourceListInvalidArgs(t *testing.T) {
"-partition=default", "-partition=default",
}, },
expectedCode: 1, expectedCode: 1,
expectedErr: errors.New("Must include resource type argument in group.verion.kind format"), expectedErr: errors.New("Must include resource type argument in group.version.kind format"),
}, },
"resource name is provided": { "resource name is provided": {
args: []string{ args: []string{

View File

@ -98,8 +98,8 @@ func (c *cmd) Run(args []string) int {
return 1 return 1
} }
resourceTenancy = &pbresource.Tenancy{ resourceTenancy = &pbresource.Tenancy{
Namespace: c.resourceFlags.Namespace(),
Partition: c.resourceFlags.Partition(), Partition: c.resourceFlags.Partition(),
Namespace: c.resourceFlags.Namespace(),
PeerName: c.resourceFlags.Peername(), PeerName: c.resourceFlags.Peername(),
} }
} }
@ -164,8 +164,8 @@ ID {
Type = gvk("catalog.v2beta1.Service") Type = gvk("catalog.v2beta1.Service")
Name = "card-processor" Name = "card-processor"
Tenancy { Tenancy {
Namespace = "payments"
Partition = "billing" Partition = "billing"
Namespace = "payments"
PeerName = "eu" PeerName = "eu"
} }
} }

View File

@ -69,7 +69,7 @@ func TestResourceReadInvalidArgs(t *testing.T) {
"invalid resource type format": { "invalid resource type format": {
args: []string{"a.", "name", "-namespace", "default"}, args: []string{"a.", "name", "-namespace", "default"},
expectedCode: 1, expectedCode: 1,
expectedErr: errors.New("Incorrect argument format: Must provide resource type argument with either in group.verion.kind format or its shorthand name"), expectedErr: errors.New("Incorrect argument format: Must provide resource type argument with either in group.version.kind format or its shorthand name"),
}, },
} }

View File

@ -67,7 +67,7 @@ func TestResourceReadInvalidArgs(t *testing.T) {
"invalid resource type format": { "invalid resource type format": {
args: []string{"a.", "name", "-namespace", "default"}, args: []string{"a.", "name", "-namespace", "default"},
expectedCode: 1, expectedCode: 1,
expectedErr: errors.New("Incorrect argument format: Must provide resource type argument with either in group.verion.kind format or its shorthand name"), expectedErr: errors.New("Incorrect argument format: Must provide resource type argument with either in group.version.kind format or its shorthand name"),
}, },
} }

View File

@ -95,3 +95,29 @@ func (resource *ResourceGRPC) List(resourceType *pbresource.Type, resourceTenanc
return listRsp.Resources, err return listRsp.Resources, err
} }
func (resource *ResourceGRPC) Delete(resourceType *pbresource.Type, resourceTenancy *pbresource.Tenancy, resourceName string) error {
token, err := resource.C.Config.GetToken()
if err != nil {
return err
}
ctx := context.Background()
if token != "" {
ctx = metadata.AppendToOutgoingContext(context.Background(), HeaderConsulToken, token)
}
defer resource.C.Conn.Close()
_, err = resource.C.Client.Delete(ctx, &pbresource.DeleteRequest{
Id: &pbresource.ID{
Type: resourceType,
Tenancy: resourceTenancy,
Name: resourceName,
},
})
if err != nil {
return fmt.Errorf("error deleting resource: %+v", err)
}
return nil
}

View File

@ -5,8 +5,8 @@ ID {
Type = gvk("demo.v2.Artist") Type = gvk("demo.v2.Artist")
Name = "korn" Name = "korn"
Tenancy { Tenancy {
Namespace = "default"
Partition = "default" Partition = "default"
Namespace = "default"
PeerName = "local" PeerName = "local"
} }
} }

View File

@ -5,8 +5,8 @@ ID {
Type = gvk("demo.v2.Artist") Type = gvk("demo.v2.Artist")
Name = "korn" Name = "korn"
Tenancy { Tenancy {
Namespace = "default"
Partition = "default" Partition = "default"
Namespace = "default"
PeerName = "local" PeerName = "local"
} }
} }

View File

@ -4,8 +4,8 @@
D { D {
Type = gvk("demo.v2.Artist") Type = gvk("demo.v2.Artist")
Tenancy { Tenancy {
Namespace = "default"
Partition = "default" Partition = "default"
Namespace = "default"
PeerName = "local" PeerName = "local"
} }
} }

View File

@ -498,7 +498,7 @@ The following table describes the parameters you can define in the `AccessLogs`
### apiVersion ### apiVersion
Specifies the verion of the Consul API to use to apply the configuration entry. This must be set to `consul.hashicorp.com/v1alpha1`. Specifies the version of the Consul API to use to apply the configuration entry. This must be set to `consul.hashicorp.com/v1alpha1`.
#### Values #### Values