Skip to content
This repository has been archived by the owner on Aug 25, 2021. It is now read-only.

Commit

Permalink
WIP: minimal changes to support openshift
Browse files Browse the repository at this point in the history
  • Loading branch information
ishustava committed Sep 8, 2020
1 parent a1bd018 commit 8845292
Show file tree
Hide file tree
Showing 23 changed files with 198 additions and 120 deletions.
4 changes: 2 additions & 2 deletions CONTRIBUTING.md
Expand Up @@ -334,15 +334,15 @@ There are a number of `kubectl` commands available in the `helpers/kubectl.go` f
For example, to call `kubectl apply` from the test write the following:

```go
helpers.KubectlApply(t, ctx.KubectlOptions(), filepath)
helpers.KubectlApply(t, ctx.KubectlOptions(t), filepath)
```

Similarly, you can obtain Kubernetes client from your test context.
You can use it to, for example, read all services in a namespace:

```go
k8sClient := ctx.KubernetesClient(t)
services, err := k8sClient.CoreV1().Services(ctx.KubectlOptions().Namespace).List(metav1.ListOptions{})
services, err := k8sClient.CoreV1().Services(ctx.KubectlOptions(t).Namespace).List(metav1.ListOptions{})
```

To make Consul API calls, you can get the Consul client from the `consulCluster` object,
Expand Down
10 changes: 9 additions & 1 deletion templates/client-role.yaml
Expand Up @@ -9,7 +9,7 @@ metadata:
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
{{- if (or .Values.global.acls.manageSystemACLs .Values.global.enablePodSecurityPolicies) }}
{{- if (or .Values.global.acls.manageSystemACLs .Values.global.enablePodSecurityPolicies .Values.global.openshift.enabled) }}
rules:
{{- if .Values.global.enablePodSecurityPolicies }}
- apiGroups: ["policy"]
Expand All @@ -28,6 +28,14 @@ rules:
verbs:
- get
{{- end }}
{{- if .Values.global.openshift.enabled}}
- apiGroups: ["security.openshift.io"]
resources: ["securitycontextconstraints"]
resourceNames:
- hostnetwork
verbs:
- use
{{- end}}
{{- else}}
rules: []
{{- end }}
Expand Down
2 changes: 1 addition & 1 deletion templates/server-statefulset.yaml
Expand Up @@ -58,7 +58,7 @@ spec:
{{- end }}
terminationGracePeriodSeconds: 30
serviceAccountName: {{ template "consul.fullname" . }}-server
{{- if not .Values.server.disableFsGroupSecurityContext }}
{{- if not (or .Values.server.disableFsGroupSecurityContext .Values.global.openshift.enabled)}}
securityContext:
fsGroup: 1000
{{- end }}
Expand Down
1 change: 1 addition & 0 deletions templates/tls-init-job.yaml
Expand Up @@ -56,6 +56,7 @@ spec:
# Note that in the subsequent runs of the job, POST requests will
# return a 409 because these secrets would already exist;
# we are ignoring these response codes.
workingDir: /tmp
command:
- "/bin/sh"
- "-ec"
Expand Down
7 changes: 7 additions & 0 deletions test/acceptance/framework/config.go
Expand Up @@ -23,6 +23,8 @@ type TestConfig struct {
EnterpriseLicenseSecretName string
EnterpriseLicenseSecretKey string

EnableOpenshift bool

ConsulImage string
ConsulK8SImage string

Expand Down Expand Up @@ -50,6 +52,11 @@ func (t *TestConfig) HelmValuesFromConfig() (map[string]string, error) {
setIfNotEmpty(helmValues, "server.enterpriseLicense.secretKey", t.EnterpriseLicenseSecretKey)
}

// todo add tests
if t.EnableOpenshift {
setIfNotEmpty(helmValues, "global.openshift.enabled", "true")
}

setIfNotEmpty(helmValues, "global.image", t.ConsulImage)
setIfNotEmpty(helmValues, "global.imageK8S", t.ConsulK8SImage)

Expand Down
17 changes: 9 additions & 8 deletions test/acceptance/framework/consul_cluster.go
@@ -1,6 +1,7 @@
package framework

import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
Expand Down Expand Up @@ -67,7 +68,7 @@ func NewHelmCluster(

opts := &helm.Options{
SetValues: values,
KubectlOptions: ctx.KubectlOptions(),
KubectlOptions: ctx.KubectlOptions(t),
Logger: logger.TestingT,
}
return &HelmCluster{
Expand Down Expand Up @@ -106,26 +107,26 @@ func (h *HelmCluster) Destroy(t *testing.T) {
helm.Delete(t, h.helmOptions, h.releaseName, false)

// delete PVCs
h.kubernetesClient.CoreV1().PersistentVolumeClaims(h.helmOptions.KubectlOptions.Namespace).DeleteCollection(&metav1.DeleteOptions{}, metav1.ListOptions{LabelSelector: "release=" + h.releaseName})
h.kubernetesClient.CoreV1().PersistentVolumeClaims(h.helmOptions.KubectlOptions.Namespace).DeleteCollection(context.TODO(), metav1.DeleteOptions{}, metav1.ListOptions{LabelSelector: "release=" + h.releaseName})

// delete any serviceaccounts that have h.releaseName in their name
sas, err := h.kubernetesClient.CoreV1().ServiceAccounts(h.helmOptions.KubectlOptions.Namespace).List(metav1.ListOptions{})
sas, err := h.kubernetesClient.CoreV1().ServiceAccounts(h.helmOptions.KubectlOptions.Namespace).List(context.TODO(), metav1.ListOptions{})
require.NoError(t, err)
for _, sa := range sas.Items {
if strings.Contains(sa.Name, h.releaseName) {
err := h.kubernetesClient.CoreV1().ServiceAccounts(h.helmOptions.KubectlOptions.Namespace).Delete(sa.Name, nil)
err := h.kubernetesClient.CoreV1().ServiceAccounts(h.helmOptions.KubectlOptions.Namespace).Delete(context.TODO(), sa.Name, metav1.DeleteOptions{})
if !errors.IsNotFound(err) {
require.NoError(t, err)
}
}
}

// delete any secrets that have h.releaseName in their name
secrets, err := h.kubernetesClient.CoreV1().Secrets(h.helmOptions.KubectlOptions.Namespace).List(metav1.ListOptions{})
secrets, err := h.kubernetesClient.CoreV1().Secrets(h.helmOptions.KubectlOptions.Namespace).List(context.TODO(), metav1.ListOptions{})
require.NoError(t, err)
for _, secret := range secrets.Items {
if strings.Contains(secret.Name, h.releaseName) {
err := h.kubernetesClient.CoreV1().Secrets(h.helmOptions.KubectlOptions.Namespace).Delete(secret.Name, nil)
err := h.kubernetesClient.CoreV1().Secrets(h.helmOptions.KubectlOptions.Namespace).Delete(context.TODO(), secret.Name, metav1.DeleteOptions{})
if !errors.IsNotFound(err) {
require.NoError(t, err)
}
Expand Down Expand Up @@ -154,7 +155,7 @@ func (h *HelmCluster) SetupConsulClient(t *testing.T, secure bool) *api.Client {
remotePort = 8501

// get the CA
caSecret, err := h.kubernetesClient.CoreV1().Secrets(namespace).Get(h.releaseName+"-consul-ca-cert", metav1.GetOptions{})
caSecret, err := h.kubernetesClient.CoreV1().Secrets(namespace).Get(context.TODO(), h.releaseName+"-consul-ca-cert", metav1.GetOptions{})
require.NoError(t, err)
caFile, err := ioutil.TempFile("", "")
require.NoError(t, err)
Expand All @@ -168,7 +169,7 @@ func (h *HelmCluster) SetupConsulClient(t *testing.T, secure bool) *api.Client {
}

// get the ACL token
aclSecret, err := h.kubernetesClient.CoreV1().Secrets(namespace).Get(h.releaseName+"-consul-bootstrap-acl-token", metav1.GetOptions{})
aclSecret, err := h.kubernetesClient.CoreV1().Secrets(namespace).Get(context.TODO(), h.releaseName+"-consul-bootstrap-acl-token", metav1.GetOptions{})
require.NoError(t, err)

config.TLSConfig.CAFile = caFile.Name()
Expand Down
28 changes: 23 additions & 5 deletions test/acceptance/framework/environment.go
Expand Up @@ -25,7 +25,7 @@ type TestEnvironment interface {
// TestContext represents a specific context a test needs,
// for example, information about a specific Kubernetes cluster.
type TestContext interface {
KubectlOptions() *k8s.KubectlOptions
KubectlOptions(t *testing.T) *k8s.KubectlOptions
KubernetesClient(t *testing.T) kubernetes.Interface
}

Expand Down Expand Up @@ -70,25 +70,43 @@ type kubernetesContext struct {
kubeContextName string
namespace string

client kubernetes.Interface
client kubernetes.Interface
options *k8s.KubectlOptions

logDirectory string
}

func (k kubernetesContext) KubectlOptions() *k8s.KubectlOptions {
return &k8s.KubectlOptions{
func (k kubernetesContext) KubectlOptions(t *testing.T) *k8s.KubectlOptions {
if k.options != nil {
return k.options
}

k.options = &k8s.KubectlOptions{
ContextName: k.kubeContextName,
ConfigPath: k.pathToKubeConfig,
Namespace: k.namespace,
}

if k.namespace == "" {
// Otherwise, get current context from config
configPath, err := k.options.GetConfigPath(t)
require.NoError(t, err)

rawConfig, err := k8s.LoadConfigFromPath(configPath).RawConfig()
require.NoError(t, err)

contextName := helpers.KubernetesContextFromOptions(t, k.options)
k.options.Namespace = rawConfig.Contexts[contextName].Namespace
}
return k.options
}

func (k kubernetesContext) KubernetesClient(t *testing.T) kubernetes.Interface {
if k.client != nil {
return k.client
}

k.client = helpers.KubernetesClientFromOptions(t, k.KubectlOptions())
k.client = helpers.KubernetesClientFromOptions(t, k.KubectlOptions(t))

return k.client
}
Expand Down
11 changes: 9 additions & 2 deletions test/acceptance/framework/flags.go
Expand Up @@ -20,6 +20,8 @@ type TestFlags struct {
flagEnterpriseLicenseSecretName string
flagEnterpriseLicenseSecretKey string

flagEnableOpenshift bool

flagConsulImage string
flagConsulK8sImage string

Expand All @@ -42,7 +44,7 @@ func (t *TestFlags) init() {
"the default kubeconfig path (~/.kube/config) will be used.")
flag.StringVar(&t.flagKubecontext, "kubecontext", "", "The name of the Kubernetes context to use. If this is blank, "+
"the context set as the current context will be used by default.")
flag.StringVar(&t.flagNamespace, "namespace", "default", "The Kubernetes namespace to use for tests.")
flag.StringVar(&t.flagNamespace, "namespace", "", "The Kubernetes namespace to use for tests.")

flag.StringVar(&t.flagConsulImage, "consul-image", "", "The Consul image to use for all tests.")
flag.StringVar(&t.flagConsulK8sImage, "consul-k8s-image", "", "The consul-k8s image to use for all tests.")
Expand All @@ -54,7 +56,7 @@ func (t *TestFlags) init() {
"If this is blank, the default kubeconfig path (~/.kube/config) will be used.")
flag.StringVar(&t.flagSecondaryKubecontext, "secondary-kubecontext", "", "The name of the Kubernetes context for the secondary cluster to use. "+
"If this is blank, the context set as the current context will be used by default.")
flag.StringVar(&t.flagSecondaryNamespace, "secondary-namespace", "default", "The Kubernetes namespace to use in the secondary k8s cluster.")
flag.StringVar(&t.flagSecondaryNamespace, "secondary-namespace", "", "The Kubernetes namespace to use in the secondary k8s cluster.")

flag.BoolVar(&t.flagEnableEnterprise, "enable-enterprise", false,
"If true, the test suite will run tests for enterprise features. "+
Expand All @@ -64,6 +66,9 @@ func (t *TestFlags) init() {
flag.StringVar(&t.flagEnterpriseLicenseSecretKey, "enterprise-license-secret-key", "",
"The key of the Kubernetes secret containing the enterprise license.")

flag.BoolVar(&t.flagEnableOpenshift, "enable-openshift", false,
"If true, the tests will automatically add Openshift Helm value for each Helm install.")

flag.BoolVar(&t.flagNoCleanupOnFailure, "no-cleanup-on-failure", false,
"If true, the tests will not cleanup Kubernetes resources they create when they finish running."+
"Note this flag must be run with -failfast flag, otherwise subsequent tests will fail.")
Expand Down Expand Up @@ -105,6 +110,8 @@ func (t *TestFlags) testConfigFromFlags() *TestConfig {
EnterpriseLicenseSecretName: t.flagEnterpriseLicenseSecretName,
EnterpriseLicenseSecretKey: t.flagEnterpriseLicenseSecretKey,

EnableOpenshift: t.flagEnableOpenshift,

ConsulImage: t.flagConsulImage,
ConsulK8SImage: t.flagConsulK8sImage,

Expand Down
14 changes: 7 additions & 7 deletions test/acceptance/go.mod
Expand Up @@ -3,13 +3,13 @@ module github.com/hashicorp/consul-helm/test/acceptance
go 1.14

require (
github.com/gruntwork-io/terratest v0.27.3
github.com/hashicorp/consul/api v1.5.0
github.com/hashicorp/consul/sdk v0.5.0
github.com/hashicorp/serf v0.9.0
github.com/gruntwork-io/terratest v0.29.0
github.com/hashicorp/consul/api v1.6.0
github.com/hashicorp/consul/sdk v0.6.0
github.com/hashicorp/serf v0.9.3
github.com/stretchr/testify v1.5.1
gopkg.in/yaml.v2 v2.2.8
k8s.io/api v0.17.0
k8s.io/apimachinery v0.17.0
k8s.io/client-go v0.17.0
k8s.io/api v0.18.3
k8s.io/apimachinery v0.18.3
k8s.io/client-go v0.18.3
)

0 comments on commit 8845292

Please sign in to comment.