Merge pull request #10155 from hashicorp/dnephin/config-entry-remove-fields
config-entry: remove Kind and Name field from Mesh config entry
This commit is contained in:
commit
55f620d636
|
@ -4173,7 +4173,6 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
|
|||
"bootstrap": [
|
||||
{
|
||||
"kind": "mesh",
|
||||
"name": "mesh",
|
||||
"meta" : {
|
||||
"foo": "bar",
|
||||
"gir": "zim"
|
||||
|
@ -4190,7 +4189,6 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
|
|||
config_entries {
|
||||
bootstrap {
|
||||
kind = "mesh"
|
||||
name = "mesh"
|
||||
meta {
|
||||
"foo" = "bar"
|
||||
"gir" = "zim"
|
||||
|
@ -4206,8 +4204,6 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
|
|||
rt.DataDir = dataDir
|
||||
rt.ConfigEntryBootstrap = []structs.ConfigEntry{
|
||||
&structs.MeshConfigEntry{
|
||||
Kind: structs.MeshConfig,
|
||||
Name: structs.MeshConfigMesh,
|
||||
Meta: map[string]string{
|
||||
"foo": "bar",
|
||||
"gir": "zim",
|
||||
|
@ -4228,7 +4224,6 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
|
|||
"bootstrap": [
|
||||
{
|
||||
"Kind": "mesh",
|
||||
"Name": "mesh",
|
||||
"Meta" : {
|
||||
"foo": "bar",
|
||||
"gir": "zim"
|
||||
|
@ -4245,7 +4240,6 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
|
|||
config_entries {
|
||||
bootstrap {
|
||||
Kind = "mesh"
|
||||
Name = "mesh"
|
||||
Meta {
|
||||
"foo" = "bar"
|
||||
"gir" = "zim"
|
||||
|
@ -4261,8 +4255,6 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
|
|||
rt.DataDir = dataDir
|
||||
rt.ConfigEntryBootstrap = []structs.ConfigEntry{
|
||||
&structs.MeshConfigEntry{
|
||||
Kind: structs.MeshConfig,
|
||||
Name: structs.MeshConfigMesh,
|
||||
Meta: map[string]string{
|
||||
"foo": "bar",
|
||||
"gir": "zim",
|
||||
|
|
|
@ -7,10 +7,11 @@ import (
|
|||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/consul/agent/structs"
|
||||
"github.com/hashicorp/consul/testrpc"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/hashicorp/consul/agent/structs"
|
||||
"github.com/hashicorp/consul/testrpc"
|
||||
)
|
||||
|
||||
func TestConfig_Get(t *testing.T) {
|
||||
|
@ -48,6 +49,18 @@ func TestConfig_Get(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Datacenter: "dc1",
|
||||
Entry: &structs.MeshConfigEntry{
|
||||
TransparentProxy: structs.TransparentProxyMeshConfig{
|
||||
CatalogDestinationsOnly: true,
|
||||
},
|
||||
Meta: map[string]string{
|
||||
"key1": "value1",
|
||||
"key2": "value2",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, req := range reqs {
|
||||
out := false
|
||||
|
@ -95,6 +108,37 @@ func TestConfig_Get(t *testing.T) {
|
|||
_, err := a.srv.Config(resp, req)
|
||||
require.Error(t, errors.New("Must provide either a kind or both kind and name"), err)
|
||||
})
|
||||
t.Run("get the single mesh config", func(t *testing.T) {
|
||||
req, _ := http.NewRequest("GET", "/v1/config/mesh/mesh", nil)
|
||||
resp := httptest.NewRecorder()
|
||||
obj, err := a.srv.Config(resp, req)
|
||||
require.NoError(t, err)
|
||||
|
||||
ce, ok := obj.(*structs.MeshConfigEntry)
|
||||
require.True(t, ok, "wrong type %T", obj)
|
||||
// Set indexes to expected values for assertions
|
||||
ce.CreateIndex = 12
|
||||
ce.ModifyIndex = 13
|
||||
|
||||
out, err := a.srv.marshalJSON(req, obj)
|
||||
require.NoError(t, err)
|
||||
|
||||
expected := `
|
||||
{
|
||||
"Kind": "mesh",
|
||||
"TransparentProxy": {
|
||||
"CatalogDestinationsOnly": true
|
||||
},
|
||||
"Meta":{
|
||||
"key1": "value1",
|
||||
"key2": "value2"
|
||||
},
|
||||
"CreateIndex": 12,
|
||||
"ModifyIndex": 13
|
||||
}
|
||||
`
|
||||
require.JSONEq(t, expected, string(out))
|
||||
})
|
||||
}
|
||||
|
||||
func TestConfig_Delete(t *testing.T) {
|
||||
|
|
|
@ -162,8 +162,10 @@ func (c *ConfigEntry) List(args *structs.ConfigEntryQuery, reply *structs.Indexe
|
|||
return err
|
||||
}
|
||||
|
||||
if args.Kind != "" && !structs.ValidateConfigEntryKind(args.Kind) {
|
||||
return fmt.Errorf("invalid config entry kind: %s", args.Kind)
|
||||
if args.Kind != "" {
|
||||
if _, err := structs.MakeConfigEntry(args.Kind, ""); err != nil {
|
||||
return fmt.Errorf("invalid config entry kind: %s", args.Kind)
|
||||
}
|
||||
}
|
||||
|
||||
return c.srv.blockingQuery(
|
||||
|
|
|
@ -428,8 +428,6 @@ func TestFSM_SnapshotRestore_OSS(t *testing.T) {
|
|||
|
||||
// mesh config entry
|
||||
meshConfig := &structs.MeshConfigEntry{
|
||||
Kind: structs.MeshConfig,
|
||||
Name: structs.MeshConfigMesh,
|
||||
TransparentProxy: structs.TransparentProxyMeshConfig{
|
||||
CatalogDestinationsOnly: true,
|
||||
},
|
||||
|
|
|
@ -1674,8 +1674,6 @@ func TestState_WatchesAndUpdates(t *testing.T) {
|
|||
CorrelationID: meshConfigEntryID,
|
||||
Result: &structs.ConfigEntryResponse{
|
||||
Entry: &structs.MeshConfigEntry{
|
||||
Kind: structs.MeshConfig,
|
||||
Name: structs.MeshConfigMesh,
|
||||
TransparentProxy: structs.TransparentProxyMeshConfig{},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -529,27 +529,12 @@ func MakeConfigEntry(kind, name string) (ConfigEntry, error) {
|
|||
case ServiceIntentions:
|
||||
return &ServiceIntentionsConfigEntry{Name: name}, nil
|
||||
case MeshConfig:
|
||||
return &MeshConfigEntry{Name: name}, nil
|
||||
return &MeshConfigEntry{}, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("invalid config entry kind: %s", kind)
|
||||
}
|
||||
}
|
||||
|
||||
func ValidateConfigEntryKind(kind string) bool {
|
||||
switch kind {
|
||||
case ServiceDefaults, ProxyDefaults:
|
||||
return true
|
||||
case ServiceRouter, ServiceSplitter, ServiceResolver:
|
||||
return true
|
||||
case IngressGateway, TerminatingGateway:
|
||||
return true
|
||||
case ServiceIntentions:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// ConfigEntryQuery is used when requesting info about a config entry.
|
||||
type ConfigEntryQuery struct {
|
||||
Kind string
|
||||
|
|
|
@ -1,15 +1,13 @@
|
|||
package structs
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/consul/acl"
|
||||
)
|
||||
|
||||
type MeshConfigEntry struct {
|
||||
Kind string
|
||||
Name string
|
||||
|
||||
// TransparentProxy contains cluster-wide options pertaining to TPROXY mode
|
||||
// when enabled.
|
||||
TransparentProxy TransparentProxyMeshConfig `alias:"transparent_proxy"`
|
||||
|
@ -36,7 +34,7 @@ func (e *MeshConfigEntry) GetName() string {
|
|||
return ""
|
||||
}
|
||||
|
||||
return e.Name
|
||||
return MeshConfigMesh
|
||||
}
|
||||
|
||||
func (e *MeshConfigEntry) GetMeta() map[string]string {
|
||||
|
@ -51,11 +49,7 @@ func (e *MeshConfigEntry) Normalize() error {
|
|||
return fmt.Errorf("config entry is nil")
|
||||
}
|
||||
|
||||
e.Kind = MeshConfig
|
||||
e.Name = MeshConfigMesh
|
||||
|
||||
e.EnterpriseMeta.Normalize()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -63,11 +57,6 @@ func (e *MeshConfigEntry) Validate() error {
|
|||
if e == nil {
|
||||
return fmt.Errorf("config entry is nil")
|
||||
}
|
||||
|
||||
if e.Name != MeshConfigMesh {
|
||||
return fmt.Errorf("invalid name (%q), only %q is supported", e.Name, MeshConfigMesh)
|
||||
}
|
||||
|
||||
if err := validateConfigEntryMeta(e.Meta); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -100,3 +89,19 @@ func (e *MeshConfigEntry) GetEnterpriseMeta() *EnterpriseMeta {
|
|||
|
||||
return &e.EnterpriseMeta
|
||||
}
|
||||
|
||||
// MarshalJSON adds the Kind field so that the JSON can be decoded back into the
|
||||
// correct type.
|
||||
// This method is implemented on the structs type (as apposed to the api type)
|
||||
// because that is what the API currently uses to return a response.
|
||||
func (e *MeshConfigEntry) MarshalJSON() ([]byte, error) {
|
||||
type Alias MeshConfigEntry
|
||||
source := &struct {
|
||||
Kind string
|
||||
*Alias
|
||||
}{
|
||||
Kind: MeshConfig,
|
||||
Alias: (*Alias)(e),
|
||||
}
|
||||
return json.Marshal(source)
|
||||
}
|
||||
|
|
|
@ -19,6 +19,9 @@ func validateUnusedKeys(unused []string) error {
|
|||
for _, k := range unused {
|
||||
switch {
|
||||
case k == "CreateIndex" || k == "ModifyIndex":
|
||||
case k == "kind" || k == "Kind":
|
||||
// The kind field is used to determine the target, but doesn't need
|
||||
// to exist on the target.
|
||||
case strings.HasSuffix(strings.ToLower(k), "namespace"):
|
||||
err = multierror.Append(err, fmt.Errorf("invalid config key %q, namespaces are a consul enterprise feature", k))
|
||||
default:
|
||||
|
|
|
@ -1310,7 +1310,6 @@ func TestDecodeConfigEntry(t *testing.T) {
|
|||
name: "mesh",
|
||||
snake: `
|
||||
kind = "mesh"
|
||||
name = "mesh"
|
||||
meta {
|
||||
"foo" = "bar"
|
||||
"gir" = "zim"
|
||||
|
@ -1321,7 +1320,6 @@ func TestDecodeConfigEntry(t *testing.T) {
|
|||
`,
|
||||
camel: `
|
||||
Kind = "mesh"
|
||||
Name = "mesh"
|
||||
Meta {
|
||||
"foo" = "bar"
|
||||
"gir" = "zim"
|
||||
|
@ -1331,8 +1329,6 @@ func TestDecodeConfigEntry(t *testing.T) {
|
|||
}
|
||||
`,
|
||||
expect: &MeshConfigEntry{
|
||||
Kind: MeshConfig,
|
||||
Name: MeshConfigMesh,
|
||||
Meta: map[string]string{
|
||||
"foo": "bar",
|
||||
"gir": "zim",
|
||||
|
|
|
@ -550,8 +550,6 @@ func TestListenersFromSnapshot(t *testing.T) {
|
|||
|
||||
snap.ConnectProxy.MeshConfigSet = true
|
||||
snap.ConnectProxy.MeshConfig = &structs.MeshConfigEntry{
|
||||
Kind: structs.MeshConfig,
|
||||
Name: structs.MeshConfigMesh,
|
||||
TransparentProxy: structs.TransparentProxyMeshConfig{
|
||||
CatalogDestinationsOnly: true,
|
||||
},
|
||||
|
|
|
@ -295,7 +295,7 @@ func makeConfigEntry(kind, name string) (ConfigEntry, error) {
|
|||
case ServiceIntentions:
|
||||
return &ServiceIntentionsConfigEntry{Kind: kind, Name: name}, nil
|
||||
case MeshConfig:
|
||||
return &MeshConfigEntry{Kind: kind, Name: name}, nil
|
||||
return &MeshConfigEntry{}, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("invalid config entry kind: %s", kind)
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package api
|
||||
|
||||
import "encoding/json"
|
||||
|
||||
type MeshConfigEntry struct {
|
||||
Kind string
|
||||
Name string
|
||||
Namespace string `json:",omitempty"`
|
||||
TransparentProxy TransparentProxyMeshConfig `alias:"transparent_proxy"`
|
||||
Meta map[string]string `json:",omitempty"`
|
||||
|
@ -15,11 +15,11 @@ type TransparentProxyMeshConfig struct {
|
|||
}
|
||||
|
||||
func (e *MeshConfigEntry) GetKind() string {
|
||||
return e.Kind
|
||||
return MeshConfig
|
||||
}
|
||||
|
||||
func (e *MeshConfigEntry) GetName() string {
|
||||
return e.Name
|
||||
return MeshConfigMesh
|
||||
}
|
||||
|
||||
func (e *MeshConfigEntry) GetNamespace() string {
|
||||
|
@ -37,3 +37,17 @@ func (e *MeshConfigEntry) GetCreateIndex() uint64 {
|
|||
func (e *MeshConfigEntry) GetModifyIndex() uint64 {
|
||||
return e.ModifyIndex
|
||||
}
|
||||
|
||||
// MarshalJSON adds the Kind field so that the JSON can be decoded back into the
|
||||
// correct type.
|
||||
func (e *MeshConfigEntry) MarshalJSON() ([]byte, error) {
|
||||
type Alias MeshConfigEntry
|
||||
source := &struct {
|
||||
Kind string
|
||||
*Alias
|
||||
}{
|
||||
Kind: MeshConfig,
|
||||
Alias: (*Alias)(e),
|
||||
}
|
||||
return json.Marshal(source)
|
||||
}
|
||||
|
|
|
@ -196,6 +196,64 @@ func TestAPI_ConfigEntries(t *testing.T) {
|
|||
_, _, err = config_entries.Get(ServiceDefaults, "foo", nil)
|
||||
require.Error(t, err)
|
||||
})
|
||||
|
||||
t.Run("Mesh", func(t *testing.T) {
|
||||
mesh := &MeshConfigEntry{
|
||||
TransparentProxy: TransparentProxyMeshConfig{CatalogDestinationsOnly: true},
|
||||
Meta: map[string]string{
|
||||
"foo": "bar",
|
||||
"gir": "zim",
|
||||
},
|
||||
}
|
||||
ce := c.ConfigEntries()
|
||||
|
||||
runStep(t, "set and get", func(t *testing.T) {
|
||||
_, wm, err := ce.Set(mesh, nil)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, wm)
|
||||
require.NotEqual(t, 0, wm.RequestTime)
|
||||
|
||||
entry, qm, err := ce.Get(MeshConfig, MeshConfigMesh, nil)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, qm)
|
||||
require.NotEqual(t, 0, qm.RequestTime)
|
||||
|
||||
result, ok := entry.(*MeshConfigEntry)
|
||||
require.True(t, ok)
|
||||
|
||||
// ignore indexes
|
||||
result.CreateIndex = 0
|
||||
result.ModifyIndex = 0
|
||||
require.Equal(t, mesh, result)
|
||||
})
|
||||
|
||||
runStep(t, "list", func(t *testing.T) {
|
||||
entries, qm, err := ce.List(MeshConfig, nil)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, qm)
|
||||
require.NotEqual(t, 0, qm.RequestTime)
|
||||
require.Len(t, entries, 1)
|
||||
})
|
||||
|
||||
runStep(t, "delete", func(t *testing.T) {
|
||||
wm, err := ce.Delete(MeshConfig, MeshConfigMesh, nil)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, wm)
|
||||
require.NotEqual(t, 0, wm.RequestTime)
|
||||
|
||||
// verify deletion
|
||||
_, _, err = ce.Get(MeshConfig, MeshConfigMesh, nil)
|
||||
require.Error(t, err)
|
||||
})
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func runStep(t *testing.T, name string, fn func(t *testing.T)) {
|
||||
t.Helper()
|
||||
if !t.Run(name, fn) {
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecodeConfigEntry(t *testing.T) {
|
||||
|
@ -1141,7 +1199,6 @@ func TestDecodeConfigEntry(t *testing.T) {
|
|||
body: `
|
||||
{
|
||||
"Kind": "mesh",
|
||||
"Name": "mesh",
|
||||
"Meta" : {
|
||||
"foo": "bar",
|
||||
"gir": "zim"
|
||||
|
@ -1152,8 +1209,6 @@ func TestDecodeConfigEntry(t *testing.T) {
|
|||
}
|
||||
`,
|
||||
expect: &MeshConfigEntry{
|
||||
Kind: "mesh",
|
||||
Name: "mesh",
|
||||
Meta: map[string]string{
|
||||
"foo": "bar",
|
||||
"gir": "zim",
|
||||
|
|
|
@ -6,13 +6,14 @@ import (
|
|||
"io"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/go-multierror"
|
||||
"github.com/mitchellh/cli"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
|
||||
"github.com/hashicorp/consul/api"
|
||||
"github.com/hashicorp/consul/command/flags"
|
||||
"github.com/hashicorp/consul/command/helpers"
|
||||
"github.com/hashicorp/consul/lib/decode"
|
||||
"github.com/hashicorp/go-multierror"
|
||||
"github.com/mitchellh/cli"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
)
|
||||
|
||||
func New(ui cli.Ui) *cmd {
|
||||
|
@ -155,6 +156,12 @@ func newDecodeConfigEntry(raw map[string]interface{}) (api.ConfigEntry, error) {
|
|||
}
|
||||
|
||||
for _, k := range md.Unused {
|
||||
switch k {
|
||||
case "kind", "Kind":
|
||||
// The kind field is used to determine the target, but doesn't need
|
||||
// to exist on the target.
|
||||
continue
|
||||
}
|
||||
err = multierror.Append(err, fmt.Errorf("invalid config key %q", k))
|
||||
}
|
||||
if err != nil {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package write
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"strings"
|
||||
"testing"
|
||||
|
@ -113,6 +114,36 @@ func TestConfigWrite(t *testing.T) {
|
|||
require.NotEqual(t, 0, code)
|
||||
require.NotEmpty(t, ui.ErrorWriter.String())
|
||||
})
|
||||
|
||||
t.Run("mesh config entry", func(t *testing.T) {
|
||||
stdin := new(bytes.Buffer)
|
||||
stdin.WriteString(`
|
||||
kind = "mesh"
|
||||
meta {
|
||||
"foo" = "bar"
|
||||
"gir" = "zim"
|
||||
}
|
||||
transparent_proxy {
|
||||
catalog_destinations_only = true
|
||||
}
|
||||
`)
|
||||
|
||||
ui := cli.NewMockUi()
|
||||
c := New(ui)
|
||||
c.testStdin = stdin
|
||||
|
||||
code := c.Run([]string{"-http-addr=" + a.HTTPAddr(), "-"})
|
||||
require.Empty(t, ui.ErrorWriter.String())
|
||||
require.Contains(t, ui.OutputWriter.String(),
|
||||
`Config entry written: mesh/mesh`)
|
||||
require.Equal(t, 0, code)
|
||||
|
||||
entry, _, err := client.ConfigEntries().Get(api.MeshConfig, api.MeshConfigMesh, nil)
|
||||
require.NoError(t, err)
|
||||
proxy, ok := entry.(*api.MeshConfigEntry)
|
||||
require.True(t, ok)
|
||||
require.Equal(t, map[string]string{"foo": "bar", "gir": "zim"}, proxy.Meta)
|
||||
})
|
||||
}
|
||||
|
||||
// TestParseConfigEntry is the 'api' mirror image of
|
||||
|
@ -2627,7 +2658,6 @@ func TestParseConfigEntry(t *testing.T) {
|
|||
name: "mesh",
|
||||
snake: `
|
||||
kind = "mesh"
|
||||
name = "mesh"
|
||||
meta {
|
||||
"foo" = "bar"
|
||||
"gir" = "zim"
|
||||
|
@ -2638,7 +2668,6 @@ func TestParseConfigEntry(t *testing.T) {
|
|||
`,
|
||||
camel: `
|
||||
Kind = "mesh"
|
||||
Name = "mesh"
|
||||
Meta {
|
||||
"foo" = "bar"
|
||||
"gir" = "zim"
|
||||
|
@ -2650,7 +2679,6 @@ func TestParseConfigEntry(t *testing.T) {
|
|||
snakeJSON: `
|
||||
{
|
||||
"kind": "mesh",
|
||||
"name": "mesh",
|
||||
"meta" : {
|
||||
"foo": "bar",
|
||||
"gir": "zim"
|
||||
|
@ -2663,7 +2691,6 @@ func TestParseConfigEntry(t *testing.T) {
|
|||
camelJSON: `
|
||||
{
|
||||
"Kind": "mesh",
|
||||
"Name": "mesh",
|
||||
"Meta" : {
|
||||
"foo": "bar",
|
||||
"gir": "zim"
|
||||
|
@ -2674,8 +2701,6 @@ func TestParseConfigEntry(t *testing.T) {
|
|||
}
|
||||
`,
|
||||
expect: &api.MeshConfigEntry{
|
||||
Kind: api.MeshConfig,
|
||||
Name: api.MeshConfigMesh,
|
||||
Meta: map[string]string{
|
||||
"foo": "bar",
|
||||
"gir": "zim",
|
||||
|
|
Loading…
Reference in New Issue