diff --git a/charts/consul/templates/controller-deployment.yaml b/charts/consul/templates/controller-deployment.yaml index 5cee3b4cde..ccf5270efd 100644 --- a/charts/consul/templates/controller-deployment.yaml +++ b/charts/consul/templates/controller-deployment.yaml @@ -64,6 +64,9 @@ spec: -log-json={{ .Values.global.logJSON }} \ -webhook-tls-cert-dir=/tmp/controller-webhook/certs \ -datacenter={{ .Values.global.datacenter }} \ + {{- if .Values.global.adminPartitions.enabled }} + -partition={{ .Values.global.adminPartitions.name }} \ + {{- end }} -enable-leader-election \ {{- if .Values.global.enableConsulNamespaces }} -enable-namespaces=true \ diff --git a/charts/consul/templates/crd-servicedefaults.yaml b/charts/consul/templates/crd-servicedefaults.yaml index 5f6443be43..329a4d35bd 100644 --- a/charts/consul/templates/crd-servicedefaults.yaml +++ b/charts/consul/templates/crd-servicedefaults.yaml @@ -206,6 +206,10 @@ spec: description: Namespace is only accepted within a service-defaults config entry. type: string + partition: + description: Partition is only accepted within a service-defaults + config entry. + type: string passiveHealthCheck: description: PassiveHealthCheck configuration determines how upstream proxy instances will be monitored for removal from @@ -294,6 +298,10 @@ spec: description: Namespace is only accepted within a service-defaults config entry. type: string + partition: + description: Partition is only accepted within a service-defaults + config entry. + type: string passiveHealthCheck: description: PassiveHealthCheck configuration determines how upstream proxy instances will be monitored for removal diff --git a/charts/consul/templates/crd-serviceintentions.yaml b/charts/consul/templates/crd-serviceintentions.yaml index d3c8dbe45a..7901083e3f 100644 --- a/charts/consul/templates/crd-serviceintentions.yaml +++ b/charts/consul/templates/crd-serviceintentions.yaml @@ -96,6 +96,9 @@ spec: namespace: description: Namespace is the namespace for the Name parameter. type: string + partition: + description: Partition is the Admin Partition for the Name parameter. + type: string permissions: description: Permissions is the list of all additional L7 attributes that extend the intention match criteria. Permission precedence diff --git a/charts/consul/test/unit/controller-deployment.bats b/charts/consul/test/unit/controller-deployment.bats index d78b7654c5..12c1a3d62d 100644 --- a/charts/consul/test/unit/controller-deployment.bats +++ b/charts/consul/test/unit/controller-deployment.bats @@ -190,6 +190,32 @@ load _helpers [ "${actual}" = "" ] } +#-------------------------------------------------------------------- +# partitions + +@test "controller/Deployment: partitions options disabled by default" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/controller-deployment.yaml \ + --set 'controller.enabled=true' \ + . | tee /dev/stderr | + yq '.spec.template.spec.containers[0].command | any(contains("partition"))' | tee /dev/stderr) + + [ "${actual}" = "false" ] +} + +@test "controller/Deployment: partition name set with .global.adminPartitions.enabled=true" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/controller-deployment.yaml \ + --set 'controller.enabled=true' \ + --set 'global.adminPartitions.enabled=true' \ + . | tee /dev/stderr | + yq '.spec.template.spec.containers[0].command | any(contains("partition=default"))' | tee /dev/stderr) + + [ "${actual}" = "true" ] +} + #-------------------------------------------------------------------- # namespaces diff --git a/control-plane/api/v1alpha1/servicedefaults_types.go b/control-plane/api/v1alpha1/servicedefaults_types.go index ba3127bd4a..8ad227b671 100644 --- a/control-plane/api/v1alpha1/servicedefaults_types.go +++ b/control-plane/api/v1alpha1/servicedefaults_types.go @@ -89,6 +89,8 @@ type Upstream struct { Name string `json:"name,omitempty"` // Namespace is only accepted within a service-defaults config entry. Namespace string `json:"namespace,omitempty"` + // Partition is only accepted within a service-defaults config entry. + Partition string `json:"partition,omitempty"` // EnvoyListenerJSON is a complete override ("escape hatch") for the upstream's // listener. // Note: This escape hatch is NOT compatible with the discovery chain and @@ -322,6 +324,7 @@ func (in *Upstream) toConsul() *capi.UpstreamConfig { return &capi.UpstreamConfig{ Name: in.Name, Namespace: in.Namespace, + Partition: in.Partition, EnvoyListenerJSON: in.EnvoyListenerJSON, EnvoyClusterJSON: in.EnvoyClusterJSON, Protocol: in.Protocol, diff --git a/control-plane/api/v1alpha1/servicedefaults_types_test.go b/control-plane/api/v1alpha1/servicedefaults_types_test.go index d4d0696ae1..04f86de8eb 100644 --- a/control-plane/api/v1alpha1/servicedefaults_types_test.go +++ b/control-plane/api/v1alpha1/servicedefaults_types_test.go @@ -68,6 +68,7 @@ func TestServiceDefaults_ToConsul(t *testing.T) { Defaults: &Upstream{ Name: "upstream-default", Namespace: "ns", + Partition: "part", EnvoyListenerJSON: `{"key": "value"}`, EnvoyClusterJSON: `{"key": "value"}`, Protocol: "http2", @@ -91,6 +92,7 @@ func TestServiceDefaults_ToConsul(t *testing.T) { { Name: "upstream-override-1", Namespace: "ns", + Partition: "part", EnvoyListenerJSON: `{"key": "value"}`, EnvoyClusterJSON: `{"key": "value"}`, Protocol: "http2", @@ -113,6 +115,7 @@ func TestServiceDefaults_ToConsul(t *testing.T) { { Name: "upstream-default", Namespace: "ns", + Partition: "part", EnvoyListenerJSON: `{"key": "value"}`, EnvoyClusterJSON: `{"key": "value"}`, Protocol: "http2", @@ -169,6 +172,7 @@ func TestServiceDefaults_ToConsul(t *testing.T) { Defaults: &capi.UpstreamConfig{ Name: "upstream-default", Namespace: "ns", + Partition: "part", EnvoyListenerJSON: `{"key": "value"}`, EnvoyClusterJSON: `{"key": "value"}`, Protocol: "http2", @@ -190,6 +194,7 @@ func TestServiceDefaults_ToConsul(t *testing.T) { { Name: "upstream-override-1", Namespace: "ns", + Partition: "part", EnvoyListenerJSON: `{"key": "value"}`, EnvoyClusterJSON: `{"key": "value"}`, Protocol: "http2", @@ -210,6 +215,7 @@ func TestServiceDefaults_ToConsul(t *testing.T) { { Name: "upstream-default", Namespace: "ns", + Partition: "part", EnvoyListenerJSON: `{"key": "value"}`, EnvoyClusterJSON: `{"key": "value"}`, Protocol: "http2", diff --git a/control-plane/api/v1alpha1/serviceintentions_types.go b/control-plane/api/v1alpha1/serviceintentions_types.go index 8abfe41ef9..4a9aba6eca 100644 --- a/control-plane/api/v1alpha1/serviceintentions_types.go +++ b/control-plane/api/v1alpha1/serviceintentions_types.go @@ -77,6 +77,8 @@ type SourceIntention struct { Name string `json:"name,omitempty"` // Namespace is the namespace for the Name parameter. Namespace string `json:"namespace,omitempty"` + // Partition is the Admin Partition for the Name parameter. + Partition string `json:"partition,omitempty"` // Action is required for an L4 intention, and should be set to one of // "allow" or "deny" for the action that should be taken if this intention matches a request. Action IntentionAction `json:"action,omitempty"` @@ -306,6 +308,7 @@ func (in *SourceIntention) toConsul() *capi.SourceIntention { return &capi.SourceIntention{ Name: in.Name, Namespace: in.Namespace, + Partition: in.Partition, Action: in.Action.toConsul(), Permissions: in.Permissions.toConsul(), Description: in.Description, diff --git a/control-plane/api/v1alpha1/serviceintentions_types_test.go b/control-plane/api/v1alpha1/serviceintentions_types_test.go index 27dfdb41f4..37c6808e4e 100644 --- a/control-plane/api/v1alpha1/serviceintentions_types_test.go +++ b/control-plane/api/v1alpha1/serviceintentions_types_test.go @@ -51,18 +51,21 @@ func TestServiceIntentions_MatchesConsul(t *testing.T) { { Name: "svc1", Namespace: "test", + Partition: "test", Action: "allow", Description: "allow access from svc1", }, { Name: "*", Namespace: "not-test", + Partition: "not-test", Action: "deny", Description: "disallow access from namespace not-test", }, { Name: "svc-2", Namespace: "bar", + Partition: "bar", Permissions: IntentionPermissions{ { Action: "allow", @@ -101,6 +104,7 @@ func TestServiceIntentions_MatchesConsul(t *testing.T) { { Name: "svc1", Namespace: "test", + Partition: "test", Action: "allow", Precedence: 0, Description: "allow access from svc1", @@ -108,6 +112,7 @@ func TestServiceIntentions_MatchesConsul(t *testing.T) { { Name: "*", Namespace: "not-test", + Partition: "not-test", Action: "deny", Precedence: 1, Description: "disallow access from namespace not-test", @@ -115,6 +120,7 @@ func TestServiceIntentions_MatchesConsul(t *testing.T) { { Name: "svc-2", Namespace: "bar", + Partition: "bar", Permissions: []*capi.IntentionPermission{ { Action: "allow", @@ -249,18 +255,21 @@ func TestServiceIntentions_ToConsul(t *testing.T) { { Name: "svc1", Namespace: "test", + Partition: "test", Action: "allow", Description: "allow access from svc1", }, { Name: "*", Namespace: "not-test", + Partition: "not-test", Action: "deny", Description: "disallow access from namespace not-test", }, { Name: "svc-2", Namespace: "bar", + Partition: "bar", Permissions: IntentionPermissions{ { Action: "allow", @@ -299,18 +308,21 @@ func TestServiceIntentions_ToConsul(t *testing.T) { { Name: "svc1", Namespace: "test", + Partition: "test", Action: "allow", Description: "allow access from svc1", }, { Name: "*", Namespace: "not-test", + Partition: "not-test", Action: "deny", Description: "disallow access from namespace not-test", }, { Name: "svc-2", Namespace: "bar", + Partition: "bar", Permissions: []*capi.IntentionPermission{ { Action: "allow", @@ -601,16 +613,19 @@ func TestServiceIntentions_Validate(t *testing.T) { { Name: "web", Namespace: "web", + Partition: "web", Action: "allow", }, { Name: "db", Namespace: "db", + Partition: "db", Action: "deny", }, { Name: "bar", Namespace: "bar", + Partition: "bar", Permissions: IntentionPermissions{ { Action: "allow", diff --git a/control-plane/config/crd/bases/consul.hashicorp.com_servicedefaults.yaml b/control-plane/config/crd/bases/consul.hashicorp.com_servicedefaults.yaml index bed1204c43..08da8480f1 100644 --- a/control-plane/config/crd/bases/consul.hashicorp.com_servicedefaults.yaml +++ b/control-plane/config/crd/bases/consul.hashicorp.com_servicedefaults.yaml @@ -200,6 +200,10 @@ spec: description: Namespace is only accepted within a service-defaults config entry. type: string + partition: + description: Partition is only accepted within a service-defaults + config entry. + type: string passiveHealthCheck: description: PassiveHealthCheck configuration determines how upstream proxy instances will be monitored for removal from @@ -288,6 +292,10 @@ spec: description: Namespace is only accepted within a service-defaults config entry. type: string + partition: + description: Partition is only accepted within a service-defaults + config entry. + type: string passiveHealthCheck: description: PassiveHealthCheck configuration determines how upstream proxy instances will be monitored for removal diff --git a/control-plane/config/crd/bases/consul.hashicorp.com_serviceintentions.yaml b/control-plane/config/crd/bases/consul.hashicorp.com_serviceintentions.yaml index b2af5c1ea2..d3420d1e77 100644 --- a/control-plane/config/crd/bases/consul.hashicorp.com_serviceintentions.yaml +++ b/control-plane/config/crd/bases/consul.hashicorp.com_serviceintentions.yaml @@ -90,6 +90,9 @@ spec: namespace: description: Namespace is the namespace for the Name parameter. type: string + partition: + description: Partition is the Admin Partition for the Name parameter. + type: string permissions: description: Permissions is the list of all additional L7 attributes that extend the intention match criteria. Permission precedence diff --git a/control-plane/go.mod b/control-plane/go.mod index b15a09db4b..adaedabaef 100644 --- a/control-plane/go.mod +++ b/control-plane/go.mod @@ -10,7 +10,7 @@ require ( github.com/google/go-cmp v0.5.6 github.com/google/go-querystring v1.0.0 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 - github.com/hashicorp/consul/api v1.4.1-0.20210827004034-d2e50fd130ae + github.com/hashicorp/consul/api v1.10.1-0.20210913215352-5b658d2f392d github.com/hashicorp/consul/sdk v0.8.0 github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-discover v0.0.0-20200812215701-c4b85f6ed31f diff --git a/control-plane/go.sum b/control-plane/go.sum index c3d4b34654..7a0487c1db 100644 --- a/control-plane/go.sum +++ b/control-plane/go.sum @@ -284,8 +284,8 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= -github.com/hashicorp/consul/api v1.4.1-0.20210827004034-d2e50fd130ae h1:eWcikXQgBN6yrsbANCTieR1uT+a7WoYYvGUFj8enPow= -github.com/hashicorp/consul/api v1.4.1-0.20210827004034-d2e50fd130ae/go.mod h1:sDjTOq0yUyv5G4h+BqSea7Fn6BU+XbolEz1952UB+mk= +github.com/hashicorp/consul/api v1.10.1-0.20210913215352-5b658d2f392d h1:IBMYvG34CbxQqM55tBk8aVtmIQxvcczI0BqyxmbQDBs= +github.com/hashicorp/consul/api v1.10.1-0.20210913215352-5b658d2f392d/go.mod h1:sDjTOq0yUyv5G4h+BqSea7Fn6BU+XbolEz1952UB+mk= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/consul/sdk v0.7.0/go.mod h1:fY08Y9z5SvJqevyZNy6WWPXiG3KwBPAvlcdx16zZ0fM= github.com/hashicorp/consul/sdk v0.8.0 h1:OJtKBtEjboEZvG6AOUdh4Z1Zbyu0WcxQ0qatRrZHTVU= diff --git a/control-plane/subcommand/controller/command.go b/control-plane/subcommand/controller/command.go index 939ef86775..d9b3784d9a 100644 --- a/control-plane/subcommand/controller/command.go +++ b/control-plane/subcommand/controller/command.go @@ -7,9 +7,11 @@ import ( "github.com/hashicorp/consul-k8s/control-plane/api/common" "github.com/hashicorp/consul-k8s/control-plane/api/v1alpha1" + "github.com/hashicorp/consul-k8s/control-plane/consul" "github.com/hashicorp/consul-k8s/control-plane/controller" cmdCommon "github.com/hashicorp/consul-k8s/control-plane/subcommand/common" "github.com/hashicorp/consul-k8s/control-plane/subcommand/flags" + "github.com/hashicorp/consul/api" "github.com/mitchellh/cli" "go.uber.org/zap/zapcore" "k8s.io/apimachinery/pkg/runtime" @@ -30,6 +32,7 @@ type Command struct { flagEnableLeaderElection bool flagEnableWebhooks bool flagDatacenter string + flagPartition string flagLogLevel string flagLogJSON bool @@ -62,6 +65,8 @@ func (c *Command) init() { "Enabling this will ensure there is only one active controller manager.") c.flagSet.StringVar(&c.flagDatacenter, "datacenter", "", "Name of the Consul datacenter the controller is operating in. This is added as metadata on managed custom resources.") + c.flagSet.StringVar(&c.flagPartition, "partition", "", + "Name of the Consul Admin Partition the controller is operating in. The config entries are created in this partition.") c.flagSet.BoolVar(&c.flagEnableNamespaces, "enable-namespaces", false, "[Enterprise Only] Enables Consul Enterprise namespaces, in either a single Consul namespace or mirrored.") c.flagSet.StringVar(&c.flagConsulDestinationNamespace, "consul-destination-namespace", "default", @@ -128,7 +133,10 @@ func (c *Command) Run(args []string) int { return 1 } - consulClient, err := c.httpFlags.APIClient() + cfg := api.DefaultConfig() + c.httpFlags.MergeOntoConfig(cfg) + cfg.Partition = c.flagPartition + consulClient, err := consul.NewClient(cfg) if err != nil { setupLog.Error(err, "connecting to Consul agent") return 1