From 37bdad37b17088b71036d7cc0a9a4732fcaf3f73 Mon Sep 17 00:00:00 2001 From: Ashwin Venkatesh Date: Wed, 15 Sep 2021 18:02:38 -0400 Subject: [PATCH] Update ConfigEntries to be Partition aware (#724) * Add partition support to config entries * Fail if namespaces are not enabled and admin partitions are enabled --- .../templates/connect-inject-deployment.yaml | 1 + .../templates/controller-deployment.yaml | 4 ++ .../consul/templates/crd-servicedefaults.yaml | 8 ++++ .../templates/crd-serviceintentions.yaml | 3 ++ .../test/unit/connect-inject-deployment.bats | 13 +++++++ .../test/unit/controller-deployment.bats | 38 +++++++++++++++++++ .../api/v1alpha1/servicedefaults_types.go | 3 ++ .../v1alpha1/servicedefaults_types_test.go | 6 +++ .../api/v1alpha1/serviceintentions_types.go | 3 ++ .../v1alpha1/serviceintentions_types_test.go | 15 ++++++++ .../consul.hashicorp.com_servicedefaults.yaml | 8 ++++ ...onsul.hashicorp.com_serviceintentions.yaml | 3 ++ control-plane/go.mod | 2 +- control-plane/go.sum | 4 +- .../subcommand/controller/command.go | 9 ++++- control-plane/subcommand/flags/http.go | 4 ++ 16 files changed, 120 insertions(+), 4 deletions(-) diff --git a/charts/consul/templates/connect-inject-deployment.yaml b/charts/consul/templates/connect-inject-deployment.yaml index 28336027f5..ed7266d7ee 100644 --- a/charts/consul/templates/connect-inject-deployment.yaml +++ b/charts/consul/templates/connect-inject-deployment.yaml @@ -2,6 +2,7 @@ {{- if not (or (and (ne (.Values.client.enabled | toString) "-") .Values.client.enabled) (and (eq (.Values.client.enabled | toString) "-") .Values.global.enabled)) }}{{ fail "clients must be enabled for connect injection" }}{{ end }} {{- if not .Values.client.grpc }}{{ fail "client.grpc must be true for connect injection" }}{{ end }} {{- if and .Values.connectInject.consulNamespaces.mirroringK8S (not .Values.global.enableConsulNamespaces) }}{{ fail "global.enableConsulNamespaces must be true if mirroringK8S=true" }}{{ end }} +{{- if and .Values.global.adminPartitions.enabled (not .Values.global.enableConsulNamespaces) }}{{ fail "global.enableConsulNamespaces must be true if global.adminPartitions.enabled=true" }}{{ end }} {{- if .Values.connectInject.centralConfig }}{{- if eq (toString .Values.connectInject.centralConfig.enabled) "false" }}{{ fail "connectInject.centralConfig.enabled cannot be set to false; to disable, set enable_central_service_config to false in server.extraConfig and client.extraConfig" }}{{ end -}}{{ end -}} {{- if .Values.connectInject.centralConfig }}{{- if .Values.connectInject.centralConfig.defaultProtocol }}{{ fail "connectInject.centralConfig.defaultProtocol is no longer supported; instead you must migrate to CRDs (see www.consul.io/docs/k8s/crds/upgrade-to-crds)" }}{{ end }}{{ end -}} {{- if .Values.connectInject.centralConfig }}{{ if .Values.connectInject.centralConfig.proxyDefaults }}{{- if ne (trim .Values.connectInject.centralConfig.proxyDefaults) `{}` }}{{ fail "connectInject.centralConfig.proxyDefaults is no longer supported; instead you must migrate to CRDs (see www.consul.io/docs/k8s/crds/upgrade-to-crds)" }}{{ end }}{{ end }}{{ end -}} diff --git a/charts/consul/templates/controller-deployment.yaml b/charts/consul/templates/controller-deployment.yaml index 5cee3b4cde..151c08b1e8 100644 --- a/charts/consul/templates/controller-deployment.yaml +++ b/charts/consul/templates/controller-deployment.yaml @@ -1,4 +1,5 @@ {{- if .Values.controller.enabled }} +{{- if and .Values.global.adminPartitions.enabled (not .Values.global.enableConsulNamespaces) }}{{ fail "global.enableConsulNamespaces must be true if global.adminPartitions.enabled=true" }}{{ end }} apiVersion: apps/v1 kind: Deployment metadata: @@ -64,6 +65,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/connect-inject-deployment.bats b/charts/consul/test/unit/connect-inject-deployment.bats index 03fbfbc592..8d78e0fdc7 100755 --- a/charts/consul/test/unit/connect-inject-deployment.bats +++ b/charts/consul/test/unit/connect-inject-deployment.bats @@ -694,6 +694,7 @@ EOF local actual=$(helm template \ -s templates/connect-inject-deployment.yaml \ --set 'connectInject.enabled=true' \ + --set 'global.enableConsulNamespaces=true' \ . | tee /dev/stderr | yq '.spec.template.spec.containers[0].command | any(contains("enable-partitions"))' | tee /dev/stderr) @@ -706,6 +707,7 @@ EOF -s templates/connect-inject-deployment.yaml \ --set 'connectInject.enabled=true' \ --set 'global.adminPartitions.enabled=true' \ + --set 'global.enableConsulNamespaces=true' \ . | tee /dev/stderr | yq '.spec.template.spec.containers[0].command | any(contains("enable-partitions"))' | tee /dev/stderr) @@ -724,6 +726,17 @@ EOF [ "${actual}" = "true" ] } +@test "connectInject/Deployment: fails if namespaces are disabled and .global.adminPartitions.enabled=true" { + cd `chart_dir` + run helm template \ + -s templates/connect-inject-deployment.yaml \ + --set 'global.adminPartitions.enabled=true' \ + --set 'global.enableConsulNamespaces=false' \ + --set 'connectInject.enabled=true' . + [ "$status" -eq 1 ] + [[ "$output" =~ "global.enableConsulNamespaces must be true if global.adminPartitions.enabled=true" ]] +} + #-------------------------------------------------------------------- # namespaces diff --git a/charts/consul/test/unit/controller-deployment.bats b/charts/consul/test/unit/controller-deployment.bats index d78b7654c5..158c6edaaa 100644 --- a/charts/consul/test/unit/controller-deployment.bats +++ b/charts/consul/test/unit/controller-deployment.bats @@ -190,6 +190,44 @@ 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' \ + --set 'global.enableConsulNamespaces=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' \ + --set 'global.enableConsulNamespaces=true' \ + . | tee /dev/stderr | + yq '.spec.template.spec.containers[0].command | any(contains("partition=default"))' | tee /dev/stderr) + + [ "${actual}" = "true" ] +} + +@test "controller/Deployment: fails if namespaces are disabled and .global.adminPartitions.enabled=true" { + cd `chart_dir` + run helm template \ + -s templates/controller-deployment.yaml \ + --set 'global.adminPartitions.enabled=true' \ + --set 'global.enableConsulNamespaces=false' \ + --set 'controller.enabled=true' . + [ "$status" -eq 1 ] + [[ "$output" =~ "global.enableConsulNamespaces must be true if global.adminPartitions.enabled=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..1e574d539f 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,9 @@ func (c *Command) Run(args []string) int { return 1 } - consulClient, err := c.httpFlags.APIClient() + cfg := api.DefaultConfig() + c.httpFlags.MergeOntoConfig(cfg) + consulClient, err := consul.NewClient(cfg) if err != nil { setupLog.Error(err, "connecting to Consul agent") return 1 diff --git a/control-plane/subcommand/flags/http.go b/control-plane/subcommand/flags/http.go index 8830ad5e00..b88acafcfd 100644 --- a/control-plane/subcommand/flags/http.go +++ b/control-plane/subcommand/flags/http.go @@ -23,6 +23,7 @@ type HTTPFlags struct { certFile StringValue keyFile StringValue tlsServerName StringValue + partition StringValue } func (f *HTTPFlags) Flags() *flag.FlagSet { @@ -56,6 +57,8 @@ func (f *HTTPFlags) Flags() *flag.FlagSet { fs.Var(&f.tlsServerName, "tls-server-name", "The server name to use as the SNI host when connecting via TLS. This "+ "can also be specified via the CONSUL_TLS_SERVER_NAME environment variable.") + fs.Var(&f.partition, "partition", + "[Enterprise Only] Name of the Consul Admin Partition the controller is operating in. The config entries are created in this partition.") return fs } @@ -110,6 +113,7 @@ func (f *HTTPFlags) MergeOntoConfig(c *api.Config) { f.certFile.Merge(&c.TLSConfig.CertFile) f.keyFile.Merge(&c.TLSConfig.KeyFile) f.tlsServerName.Merge(&c.TLSConfig.Address) + f.partition.Merge(&c.Partition) } func Merge(dst, src *flag.FlagSet) {