Skip to content

Commit

Permalink
Add Gateway API and Envoy Gateway install to Calico Enterprise
Browse files Browse the repository at this point in the history
  • Loading branch information
nelljerram committed Oct 31, 2024
1 parent 2c64f3a commit d03c844
Show file tree
Hide file tree
Showing 7 changed files with 35,830 additions and 6 deletions.
30 changes: 27 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -220,8 +220,32 @@ else
GIT_VERSION?=$(shell git describe --tags --dirty --always --abbrev=12)
endif

ENVOY_GATEWAY_HELM_CHART ?= oci://docker.io/envoyproxy/gateway-helm
ENVOY_GATEWAY_VERSION ?= v1.1.2
ENVOY_GATEWAY_PREFIX ?= calico-gateway
ENVOY_GATEWAY_NAMESPACE ?= calico-gateway-system

pkg/envoygateway/resources.yaml: hack/bin/helm-$(BUILDARCH)
echo "---" > $@
echo "apiVersion: v1" >> $@
echo "kind: Namespace" >> $@
echo "metadata:" >> $@
echo " name: $(ENVOY_GATEWAY_NAMESPACE)" >> $@
hack/bin/helm-$(BUILDARCH) template $(ENVOY_GATEWAY_PREFIX) $(ENVOY_GATEWAY_HELM_CHART) \
--version $(ENVOY_GATEWAY_VERSION) \
-n $(ENVOY_GATEWAY_NAMESPACE) \
--include-crds \
>> $@

hack/bin/helm-$(BUILDARCH):
mkdir -p hack/bin
curl -sSf -L --retry 5 -o hack/bin/helm3.tar.gz https://get.helm.sh/helm-v3.11.3-linux-$(BUILDARCH).tar.gz
tar -zxvf hack/bin/helm3.tar.gz -C hack/bin linux-$(BUILDARCH)/helm
mv hack/bin/linux-$(BUILDARCH)/helm hack/bin/helm-$(BUILDARCH)
rmdir hack/bin/linux-$(BUILDARCH)

build: $(BINDIR)/operator-$(ARCH)
$(BINDIR)/operator-$(ARCH): $(SRC_FILES)
$(BINDIR)/operator-$(ARCH): $(SRC_FILES) pkg/envoygateway/resources.yaml
mkdir -p $(BINDIR)
$(CONTAINERIZED) -e CGO_ENABLED=$(CGO_ENABLED) -e GOEXPERIMENT=$(GOEXPERIMENT) $(CALICO_BUILD) \
sh -c '$(GIT_CONFIG_SSH) \
Expand Down Expand Up @@ -284,14 +308,14 @@ GINKGO_ARGS?= -v -trace -r
GINKGO_FOCUS?=.*

.PHONY: ut
ut:
ut: pkg/envoygateway/resources.yaml
-mkdir -p .go-pkg-cache report
$(CONTAINERIZED) $(CALICO_BUILD) sh -c '$(GIT_CONFIG_SSH) \
ginkgo -focus="$(GINKGO_FOCUS)" $(GINKGO_ARGS) "$(UT_DIR)"'

## Run the functional tests
fv: cluster-create load-container-images run-fvs cluster-destroy
run-fvs:
run-fvs: pkg/envoygateway/resources.yaml
-mkdir -p .go-pkg-cache report
$(CONTAINERIZED) $(CALICO_BUILD) sh -c '$(GIT_CONFIG_SSH) \
ginkgo -focus="$(GINKGO_FOCUS)" $(GINKGO_ARGS) "$(FV_DIR)"'
Expand Down
20 changes: 20 additions & 0 deletions pkg/controller/installation/core_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"strings"

"github.com/elastic/cloud-on-k8s/v2/pkg/utils/stringsutil"
"github.com/tigera/operator/pkg/envoygateway"
relasticsearch "github.com/tigera/operator/pkg/render/common/elasticsearch"

"github.com/go-logr/logr"
Expand Down Expand Up @@ -1400,6 +1401,13 @@ func (r *ReconcileInstallation) Reconcile(ctx context.Context, request reconcile
)
}

installEnvoyGateway := (instance.Spec.Variant == v1.TigeraSecureEnterprise)
if installEnvoyGateway {
if err = r.installEnvoyGateway(ctx, reqLogger); err != nil {
return reconcile.Result{}, err
}
}

imageSet, err := imageset.GetImageSet(ctx, r.client, instance.Spec.Variant)
if err != nil {
r.status.SetDegraded(operator.ResourceReadError, "Error getting ImageSet", err, reqLogger)
Expand Down Expand Up @@ -1890,6 +1898,18 @@ func (r *ReconcileInstallation) updateCRDs(ctx context.Context, variant operator
return nil
}

func (r *ReconcileInstallation) installEnvoyGateway(ctx context.Context, log logr.Logger) error {
egComponent := render.NewPassthrough(envoygateway.GetResources(log)...)
// Specify nil for the CR so no ownership is put on the gateway resources. We do this so
// removing the Installation CR will not remove them.
handler := r.newComponentHandler(log, r.client, r.scheme, nil)
if err := handler.CreateOrUpdateOrDelete(ctx, egComponent, nil); err != nil {
r.status.SetDegraded(operator.ResourceUpdateError, "Error creating / updating gateway resource", err, log)
return err
}
return nil
}

func getConfigMap(client client.Client, cmName string) (*corev1.ConfigMap, error) {
cm := &corev1.ConfigMap{}
cmNamespacedName := types.NamespacedName{
Expand Down
6 changes: 6 additions & 0 deletions pkg/controller/installation/core_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"github.com/stretchr/testify/mock"

appsv1 "k8s.io/api/apps/v1"
batchv1 "k8s.io/api/batch/v1"
corev1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
schedv1 "k8s.io/api/scheduling/v1"
Expand Down Expand Up @@ -118,6 +119,7 @@ var _ = Describe("Testing core-controller installation", func() {
scheme = runtime.NewScheme()
Expect(apis.AddToScheme(scheme)).NotTo(HaveOccurred())
Expect(appsv1.SchemeBuilder.AddToScheme(scheme)).ShouldNot(HaveOccurred())
Expect(batchv1.SchemeBuilder.AddToScheme(scheme)).ShouldNot(HaveOccurred())
Expect(rbacv1.SchemeBuilder.AddToScheme(scheme)).ShouldNot(HaveOccurred())
Expect(schedv1.SchemeBuilder.AddToScheme(scheme)).ShouldNot(HaveOccurred())
Expect(operator.SchemeBuilder.AddToScheme(scheme)).NotTo(HaveOccurred())
Expand Down Expand Up @@ -561,6 +563,7 @@ var _ = Describe("Testing core-controller installation", func() {
scheme = runtime.NewScheme()
Expect(apis.AddToScheme(scheme)).NotTo(HaveOccurred())
Expect(appsv1.SchemeBuilder.AddToScheme(scheme)).ShouldNot(HaveOccurred())
Expect(batchv1.SchemeBuilder.AddToScheme(scheme)).ShouldNot(HaveOccurred())
Expect(rbacv1.SchemeBuilder.AddToScheme(scheme)).ShouldNot(HaveOccurred())
Expect(schedv1.SchemeBuilder.AddToScheme(scheme)).ShouldNot(HaveOccurred())
Expect(operator.SchemeBuilder.AddToScheme(scheme)).NotTo(HaveOccurred())
Expand Down Expand Up @@ -768,6 +771,7 @@ var _ = Describe("Testing core-controller installation", func() {
scheme = runtime.NewScheme()
Expect(apis.AddToScheme(scheme)).NotTo(HaveOccurred())
Expect(appsv1.SchemeBuilder.AddToScheme(scheme)).ShouldNot(HaveOccurred())
Expect(batchv1.SchemeBuilder.AddToScheme(scheme)).ShouldNot(HaveOccurred())
Expect(rbacv1.SchemeBuilder.AddToScheme(scheme)).ShouldNot(HaveOccurred())
Expect(schedv1.SchemeBuilder.AddToScheme(scheme)).ShouldNot(HaveOccurred())
Expect(operator.SchemeBuilder.AddToScheme(scheme)).NotTo(HaveOccurred())
Expand Down Expand Up @@ -1567,6 +1571,7 @@ var _ = Describe("Testing core-controller installation", func() {
scheme = runtime.NewScheme()
Expect(apis.AddToScheme(scheme)).NotTo(HaveOccurred())
Expect(appsv1.SchemeBuilder.AddToScheme(scheme)).ShouldNot(HaveOccurred())
Expect(batchv1.SchemeBuilder.AddToScheme(scheme)).ShouldNot(HaveOccurred())
Expect(rbacv1.SchemeBuilder.AddToScheme(scheme)).ShouldNot(HaveOccurred())
Expect(schedv1.SchemeBuilder.AddToScheme(scheme)).ShouldNot(HaveOccurred())
Expect(operator.SchemeBuilder.AddToScheme(scheme)).NotTo(HaveOccurred())
Expand Down Expand Up @@ -1704,6 +1709,7 @@ var _ = Describe("Testing core-controller installation", func() {
scheme = runtime.NewScheme()
Expect(apis.AddToScheme(scheme)).NotTo(HaveOccurred())
Expect(appsv1.SchemeBuilder.AddToScheme(scheme)).ShouldNot(HaveOccurred())
Expect(batchv1.SchemeBuilder.AddToScheme(scheme)).ShouldNot(HaveOccurred())
Expect(rbacv1.SchemeBuilder.AddToScheme(scheme)).ShouldNot(HaveOccurred())
Expect(schedv1.SchemeBuilder.AddToScheme(scheme)).ShouldNot(HaveOccurred())
Expect(operator.SchemeBuilder.AddToScheme(scheme)).NotTo(HaveOccurred())
Expand Down
8 changes: 6 additions & 2 deletions pkg/controller/utils/component.go
Original file line number Diff line number Diff line change
Expand Up @@ -760,8 +760,12 @@ func setStandardSelectorAndLabels(obj client.Object) {
if podTemplate.ObjectMeta.Labels == nil {
podTemplate.ObjectMeta.Labels = make(map[string]string)
}
podTemplate.ObjectMeta.Labels["k8s-app"] = name
podTemplate.ObjectMeta.Labels["app.kubernetes.io/name"] = name
if podTemplate.ObjectMeta.Labels["k8s-app"] == "" {
podTemplate.ObjectMeta.Labels["k8s-app"] = name
}
if podTemplate.ObjectMeta.Labels["app.kubernetes.io/name"] == "" {
podTemplate.ObjectMeta.Labels["app.kubernetes.io/name"] = name
}
}

// ReadyFlag is used to synchronize access to a boolean flag
Expand Down
140 changes: 140 additions & 0 deletions pkg/envoygateway/resources.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
// Copyright (c) 2024 Tigera, Inc. All rights reserved.

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package envoygateway

import (
_ "embed"
"fmt"
"strings"
"sync"

"github.com/go-logr/logr"
appsv1 "k8s.io/api/apps/v1"
batchv1 "k8s.io/api/batch/v1"
v1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
apiextenv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/yaml" // gopkg.in/yaml.v2 didn't parse all the fields but this package did
)

var (
//go:embed resources.yaml
resources string

yamlDelimiter = "\n---\n"
lock sync.Mutex
cachedObjects []client.Object
)

type yamlKind struct {
APIVersion string `yaml:"apiVersion"`
Kind string `yaml:"kind"`
}

func GetResources(log logr.Logger) []client.Object {
lock.Lock()
defer lock.Unlock()

if len(cachedObjects) == 0 {
for _, yml := range strings.Split(resources, yamlDelimiter) {
var yamlKind yamlKind
if err := yaml.Unmarshal([]byte(yml), &yamlKind); err != nil {
panic(fmt.Sprintf("unable to unmarshal YAML: %v:\n%v\n", err, yml))
}
kindStr := yamlKind.APIVersion + "/" + yamlKind.Kind
log.Info(kindStr)
switch kindStr {
case "apiextensions.k8s.io/v1/CustomResourceDefinition":
obj := &apiextenv1.CustomResourceDefinition{}
if err := yaml.Unmarshal([]byte(yml), obj); err != nil {
panic(fmt.Sprintf("unable to unmarshal %v: %v", kindStr, err))
}
cachedObjects = append(cachedObjects, obj)
case "apps/v1/Deployment":
obj := &appsv1.Deployment{}
if err := yaml.Unmarshal([]byte(yml), obj); err != nil {
panic(fmt.Sprintf("unable to unmarshal %v: %v", kindStr, err))
}
cachedObjects = append(cachedObjects, obj)
case "batch/v1/Job":
obj := &batchv1.Job{}
if err := yaml.Unmarshal([]byte(yml), obj); err != nil {
panic(fmt.Sprintf("unable to unmarshal %v: %v", kindStr, err))
}
cachedObjects = append(cachedObjects, obj)
case "rbac.authorization.k8s.io/v1/ClusterRole":
obj := &rbacv1.ClusterRole{}
if err := yaml.Unmarshal([]byte(yml), obj); err != nil {
panic(fmt.Sprintf("unable to unmarshal %v: %v", kindStr, err))
}
cachedObjects = append(cachedObjects, obj)
case "rbac.authorization.k8s.io/v1/ClusterRoleBinding":
obj := &rbacv1.ClusterRoleBinding{}
if err := yaml.Unmarshal([]byte(yml), obj); err != nil {
panic(fmt.Sprintf("unable to unmarshal %v: %v", kindStr, err))
}
cachedObjects = append(cachedObjects, obj)
case "rbac.authorization.k8s.io/v1/Role":
obj := &rbacv1.Role{}
if err := yaml.Unmarshal([]byte(yml), obj); err != nil {
panic(fmt.Sprintf("unable to unmarshal %v: %v", kindStr, err))
}
cachedObjects = append(cachedObjects, obj)
case "rbac.authorization.k8s.io/v1/RoleBinding":
obj := &rbacv1.RoleBinding{}
if err := yaml.Unmarshal([]byte(yml), obj); err != nil {
panic(fmt.Sprintf("unable to unmarshal %v: %v", kindStr, err))
}
cachedObjects = append(cachedObjects, obj)
case "v1/ConfigMap":
obj := &v1.ConfigMap{}
if err := yaml.Unmarshal([]byte(yml), obj); err != nil {
panic(fmt.Sprintf("unable to unmarshal %v: %v", kindStr, err))
}
cachedObjects = append(cachedObjects, obj)
case "v1/Namespace":
obj := &v1.Namespace{}
if err := yaml.Unmarshal([]byte(yml), obj); err != nil {
panic(fmt.Sprintf("unable to unmarshal %v: %v", kindStr, err))
}
cachedObjects = append(cachedObjects, obj)
case "v1/Service":
obj := &v1.Service{}
if err := yaml.Unmarshal([]byte(yml), obj); err != nil {
panic(fmt.Sprintf("unable to unmarshal %v: %v", kindStr, err))
}
cachedObjects = append(cachedObjects, obj)
case "v1/ServiceAccount":
obj := &v1.ServiceAccount{}
if err := yaml.Unmarshal([]byte(yml), obj); err != nil {
panic(fmt.Sprintf("unable to unmarshal %v: %v", kindStr, err))
}
cachedObjects = append(cachedObjects, obj)
case "/":
// No-op.
default:
panic(fmt.Sprintf("unhandled type %v", kindStr))
}
}
}

resources := make([]client.Object, len(cachedObjects))
for i := range cachedObjects {
resources[i] = cachedObjects[i].DeepCopyObject().(client.Object)
}

return resources
}
Loading

0 comments on commit d03c844

Please sign in to comment.