Skip to content

Commit

Permalink
add support of consul namespaces to health checks (#376)
Browse files Browse the repository at this point in the history
* Add support for consul namespaces to health checks for connect-injected pods
Co-authored-by: Luke Kysow <1034429+lkysow@users.noreply.github.com>
Co-authored-by: Iryna Shustava <ishustava@users.noreply.github.com>
  • Loading branch information
kschoche committed Nov 5, 2020
1 parent f5021a6 commit 0564d57
Show file tree
Hide file tree
Showing 6 changed files with 420 additions and 32 deletions.
12 changes: 12 additions & 0 deletions connect-inject/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ const (

// injected is used as the annotation value for annotationInjected
injected = "injected"

// annotationConsulNamespace is the Consul namespace the service is registered into.
annotationConsulNamespace = "consul.hashicorp.com/consul-namespace"
)

var (
Expand Down Expand Up @@ -360,6 +363,15 @@ func (h *Handler) Mutate(req *v1beta1.AdmissionRequest) *v1beta1.AdmissionRespon
labelInject: injected,
})...)

// Consul-ENT only: Add the Consul destination namespace as an annotation to the pod.
if h.EnableNamespaces {
patches = append(patches, updateAnnotation(
pod.Annotations,
map[string]string{
annotationConsulNamespace: h.consulNamespace(req.Namespace),
})...)
}

// Generate the patch
var patch []byte
if len(patches) > 0 {
Expand Down
87 changes: 87 additions & 0 deletions connect-inject/handler_ent_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
package connectinject

import (
"encoding/json"
"testing"
"time"

Expand All @@ -11,6 +12,7 @@ import (
"github.com/hashicorp/consul/sdk/testutil"
"github.com/hashicorp/consul/sdk/testutil/retry"
"github.com/hashicorp/go-hclog"
"github.com/mattbaird/jsonpatch"
"github.com/stretchr/testify/require"
"k8s.io/api/admission/v1beta1"
corev1 "k8s.io/api/core/v1"
Expand Down Expand Up @@ -508,3 +510,88 @@ func TestHandler_MutateWithNamespaces_ACLs(t *testing.T) {
})
}
}

// Test that the annotation for the Consul namespace is added.
func TestHandler_MutateWithNamespaces_Annotation(t *testing.T) {
t.Parallel()
sourceKubeNS := "kube-ns"

cases := map[string]struct {
ConsulDestinationNamespace string
Mirroring bool
MirroringPrefix string
ExpNamespaceAnnotation string
}{
"dest: default": {
ConsulDestinationNamespace: "default",
ExpNamespaceAnnotation: "default",
},
"dest: foo": {
ConsulDestinationNamespace: "foo",
ExpNamespaceAnnotation: "foo",
},
"mirroring": {
Mirroring: true,
ExpNamespaceAnnotation: sourceKubeNS,
},
"mirroring with prefix": {
Mirroring: true,
MirroringPrefix: "prefix-",
ExpNamespaceAnnotation: "prefix-" + sourceKubeNS,
},
}

for name, c := range cases {
t.Run(name, func(t *testing.T) {
require := require.New(t)

// Set up consul server
a, err := testutil.NewTestServerConfigT(t, nil)
require.NoError(err)
defer a.Stop()

// Set up consul client
client, err := api.NewClient(&api.Config{
Address: a.HTTPAddr,
})
require.NoError(err)

handler := Handler{
Log: hclog.Default().Named("handler"),
AllowK8sNamespacesSet: mapset.NewSet("*"),
DenyK8sNamespacesSet: mapset.NewSet(),
EnableNamespaces: true,
ConsulDestinationNamespace: c.ConsulDestinationNamespace,
EnableK8SNSMirroring: c.Mirroring,
K8SNSMirroringPrefix: c.MirroringPrefix,
ConsulClient: client,
}

resp := handler.Mutate(&v1beta1.AdmissionRequest{
Object: encodeRaw(t, &corev1.Pod{
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{
Name: "web",
},
},
},
}),
Namespace: sourceKubeNS,
})
require.Equal(resp.Allowed, true)

// Check that the annotation was added as a patch.
var consulNamespaceAnnotationValue string
var patches []jsonpatch.JsonPatchOperation
require.NoError(json.Unmarshal(resp.Patch, &patches))
for _, patch := range patches {
if patch.Path == "/metadata/annotations/"+escapeJSONPointer(annotationConsulNamespace) {
consulNamespaceAnnotationValue = patch.Value.(string)
}
}
require.NotEmpty(consulNamespaceAnnotationValue, "no namespace annotation set")
require.Equal(c.ExpNamespaceAnnotation, consulNamespaceAnnotationValue)
})
}
}
1 change: 1 addition & 0 deletions connect-inject/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,7 @@ func TestHandlerHandle(t *testing.T) {
},
},
},

{
"pod with existing label",
Handler{
Expand Down
3 changes: 3 additions & 0 deletions connect-inject/health_check_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,9 @@ func (h *HealthCheckResource) getConsulClient(pod *corev1.Pod) (*api.Client, err
newAddr := fmt.Sprintf("%s://%s:%s", h.ConsulUrl.Scheme, pod.Status.HostIP, h.ConsulUrl.Port())
localConfig := api.DefaultConfig()
localConfig.Address = newAddr
if pod.Annotations[annotationConsulNamespace] != "" {
localConfig.Namespace = pod.Annotations[annotationConsulNamespace]
}
localClient, err := api.NewClient(localConfig)
if err != nil {
h.Log.Error("unable to get Consul API Client", "addr", newAddr, "err", err)
Expand Down
Loading

0 comments on commit 0564d57

Please sign in to comment.