Skip to content

Commit

Permalink
Deploy networking-console-plugin by CNO
Browse files Browse the repository at this point in the history
Use the CNO operator config controller to deploy and reconcile the resources required to enable the new Networking console plugin:
* Deployment
* Service
* ConfigMap (for nginx config)
* ConsolePlugin

Signed-off-by: Oren Cohen <ocohen@redhat.com>
  • Loading branch information
orenc1 committed Mar 31, 2024
1 parent d3463da commit 8aa4cb5
Show file tree
Hide file tree
Showing 9 changed files with 308 additions and 7 deletions.
39 changes: 39 additions & 0 deletions bindata/networking-console-plugin/001-config-map.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
apiVersion: v1
data:
nginx.conf: |
error_log /dev/stdout info;
events {}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
keepalive_timeout 65;
server {
listen 9443 ssl;
ssl_certificate /var/cert/tls.crt;
ssl_certificate_key /var/cert/tls.key;
root /opt/app-root/src;
# Prevent caching for plugin-manifest.json
location = /plugin-manifest.json {
add_header Cache-Control 'no-cache, no-store, must-revalidate, proxy-revalidate, max-age=0';
add_header Pragma 'no-cache';
add_header Expires '0';
}
# Prevent caching for plugin-entry.js
location = /plugin-entry.js {
add_header Cache-Control 'no-cache, no-store, must-revalidate, proxy-revalidate, max-age=0';
add_header Pragma 'no-cache';
add_header Expires '0';
}
}
}
kind: ConfigMap
metadata:
labels:
app.kubernetes.io/component: networking-console-plugin
app.kubernetes.io/managed-by: cluster-network-operator
app.kubernetes.io/name: networking-console-plugin
app.kubernetes.io/part-of: cluster-network-operator
name: networking-console-plugin
namespace: openshift-network-operator
104 changes: 104 additions & 0 deletions bindata/networking-console-plugin/002-deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/component: networking-console-plugin
app.kubernetes.io/managed-by: cluster-network-operator
app.kubernetes.io/name: networking-console-plugin
app.kubernetes.io/part-of: cluster-network-operator
name: networking-console-plugin
namespace: openshift-network-operator
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/component: networking-console-plugin
app.kubernetes.io/managed-by: cluster-network-operator
app.kubernetes.io/name: networking-console-plugin
app.kubernetes.io/part-of: cluster-network-operator
strategy:
rollingUpdate:
maxUnavailable: 1
type: RollingUpdate
template:
metadata:
annotations:
target.workload.openshift.io/management: '{"effect": "PreferredDuringScheduling"}'
labels:
app.kubernetes.io/component: networking-console-plugin
app.kubernetes.io/managed-by: cluster-network-operator
app.kubernetes.io/name: networking-console-plugin
app.kubernetes.io/part-of: cluster-network-operator
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app.kubernetes.io/component: networking-console-plugin
app.kubernetes.io/managed-by: cluster-network-operator
app.kubernetes.io/name: networking-console-plugin
app.kubernetes.io/part-of: cluster-network-operator
namespaces:
- openshift-network-operator
topologyKey: kubernetes.io/hostname
automountServiceAccountToken: false
containers:
- command:
- /bin/sh
- -c
- |
if echo "$POD_IP" | grep -qE '^([0-9]{1,3}\.){3}[0-9]{1,3}$'; then
LISTEN_ADDRESS_PORT_REPLACED_AT_RUNTIME="9443"
else
LISTEN_ADDRESS_PORT_REPLACED_AT_RUNTIME="[::]:9443"
fi
sed "s/LISTEN_ADDRESS_PORT_REPLACED_AT_RUNTIME/$LISTEN_ADDRESS_PORT_REPLACED_AT_RUNTIME/g" /etc/nginx/nginx.conf > /tmp/nginx.conf
exec nginx -c /tmp/nginx.conf -g 'daemon off;'
env:
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
image: "{{.NetworkingConsolePluginImage}}"
imagePullPolicy: IfNotPresent
name: networking-console-plugin
ports:
- containerPort: 9443
name: https
resources:
requests:
cpu: 10m
memory: 50Mi
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
terminationMessagePolicy: FallbackToLogsOnError
volumeMounts:
- mountPath: /var/cert
name: networking-console-plugin-cert
readOnly: true
- mountPath: /etc/nginx/nginx.conf
name: nginx-conf
readOnly: true
subPath: nginx.conf
dnsPolicy: ClusterFirst
nodeSelector:
kubernetes.io/os: linux
priorityClassName: system-cluster-critical
restartPolicy: Always
securityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
volumes:
- configMap:
defaultMode: 420
name: networking-console-plugin
name: nginx-conf
- name: networking-console-plugin-cert
secret:
defaultMode: 420
secretName: networking-console-plugin-cert
24 changes: 24 additions & 0 deletions bindata/networking-console-plugin/003-service.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
apiVersion: v1
kind: Service
metadata:
annotations:
openshift.io/description: Expose the networking console plugin service on port 9443. This port is for internal use, and no other usage is guaranteed.
service.beta.openshift.io/serving-cert-secret-name: networking-console-plugin-cert
labels:
app.kubernetes.io/component: networking-console-plugin
app.kubernetes.io/managed-by: cluster-network-operator
app.kubernetes.io/name: networking-console-plugin
app.kubernetes.io/part-of: cluster-network-operator
name: networking-console-plugin
namespace: openshift-network-operator
spec:
ports:
- name: https
port: 9443
targetPort: https
selector:
app.kubernetes.io/component: networking-console-plugin
app.kubernetes.io/managed-by: cluster-network-operator
app.kubernetes.io/name: networking-console-plugin
app.kubernetes.io/part-of: cluster-network-operator
sessionAffinity: None
18 changes: 18 additions & 0 deletions bindata/networking-console-plugin/004-console-plugin.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
apiVersion: console.openshift.io/v1
kind: ConsolePlugin
metadata:
labels:
app.kubernetes.io/component: networking-console-plugin
app.kubernetes.io/managed-by: cluster-network-operator
app.kubernetes.io/name: networking-console-plugin
app.kubernetes.io/part-of: cluster-network-operator
name: networking-console-plugin
spec:
backend:
service:
basePath: /
name: networking-console-plugin
namespace: openshift-network-operator
port: 9443
type: Service
displayName: Networking Console Plugin
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ spec:
value: quay.io/openshift/origin-cluster-network-operator:latest
- name: CLOUD_NETWORK_CONFIG_CONTROLLER_IMAGE
value: quay.io/openshift/origin-cloud-network-config-controller:latest
- name: NETWORKING_CONSOLE_PLUGIN_IMAGE
value: quay.io/orenc/networking-console-plugin:4.16
- name: POD_NAME
valueFrom:
fieldRef:
Expand Down
2 changes: 2 additions & 0 deletions manifests/0000_70_cluster-network-operator_03_deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ spec:
value: "quay.io/openshift/origin-cluster-network-operator:latest"
- name: CLOUD_NETWORK_CONFIG_CONTROLLER_IMAGE
value: "quay.io/openshift/origin-cloud-network-config-controller:latest"
- name: NETWORKING_CONSOLE_PLUGIN_IMAGE
value: "quay.io/orenc/networking-console-plugin:4.16"
- name: POD_NAME
valueFrom:
fieldRef:
Expand Down
2 changes: 1 addition & 1 deletion pkg/client/fake/fake_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ func isOpenShiftObject(obj crclient.Object) bool {
return false
}

// NewFakeClient creates a fake client with a backing store that contains the given objexts.
// NewFakeClient creates a fake client with a backing store that contains the given objects.
//
// Note that, due to limitations in the test infrastructure, each client has an independent store.
// This means that changes made in, say, the crclient, won't show up in the Dynamic client or the typed
Expand Down
6 changes: 6 additions & 0 deletions pkg/client/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,9 @@ type ClusterClient interface {

AddCustomInformer(inf cache.SharedInformer)
}

type JsonPatch struct {
Op string `json:"op"`
Path string `json:"path"`
Value interface{} `json:"value,omitempty"`
}
118 changes: 112 additions & 6 deletions pkg/network/render.go
Original file line number Diff line number Diff line change
@@ -1,29 +1,38 @@
package network

import (
"github.com/openshift/cluster-network-operator/pkg/names"
"context"
"encoding/json"
"fmt"
"log"
"net"
"os"
"path/filepath"
"reflect"
"sigs.k8s.io/controller-runtime/pkg/client"
"slices"
"sort"
"strings"

"github.com/pkg/errors"

"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
apierrors "k8s.io/apimachinery/pkg/api/errors"
uns "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/sets"
utilnet "k8s.io/utils/net"
crclient "sigs.k8s.io/controller-runtime/pkg/client"

configv1 "github.com/openshift/api/config/v1"
operv1 "github.com/openshift/api/operator/v1"
"github.com/openshift/cluster-network-operator/pkg/bootstrap"
cnoclient "github.com/openshift/cluster-network-operator/pkg/client"
"github.com/openshift/cluster-network-operator/pkg/hypershift"
"github.com/openshift/cluster-network-operator/pkg/names"
"github.com/openshift/cluster-network-operator/pkg/render"
iputil "github.com/openshift/cluster-network-operator/pkg/util/ip"
"github.com/openshift/library-go/pkg/operator/configobserver/featuregates"

uns "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/util/sets"
utilnet "k8s.io/utils/net"
)

var dualStackPlatforms = sets.NewString(
Expand Down Expand Up @@ -112,19 +121,34 @@ func Render(conf *operv1.NetworkSpec, bootstrapResult *bootstrap.BootstrapResult
}
objs = append(objs, o...)

// render network public
o, err = renderNetworkPublic(manifestDir)
if err != nil {
return nil, progressing, err
}
objs = append(objs, o...)

// render
// render network node identiry
o, err = renderNetworkNodeIdentity(conf, bootstrapResult, manifestDir, client)
if err != nil {
return nil, progressing, err
}
objs = append(objs, o...)

// render networking console plugin
o, err = renderNetworkingConsolePlugin(manifestDir, client)
if err != nil {
return nil, progressing, err
}
if o != nil {
objs = append(objs, o...)
}

err = registerNetworkingConsolePlugin(client)
if err != nil {
return nil, progressing, err
}

log.Printf("Render phase done, rendered %d objects", len(objs))
return objs, progressing, nil
}
Expand Down Expand Up @@ -833,6 +857,88 @@ func renderNetworkPublic(manifestDir string) ([]*uns.Unstructured, error) {
return manifests, nil
}

// renderNetworkingConsolePlugin renders the common objects related to the networking console plugin resources
func renderNetworkingConsolePlugin(manifestDir string, cl cnoclient.Client) ([]*uns.Unstructured, error) {
if !isConsolePluginCRDExist(cl) {
return nil, nil
}
data := render.MakeRenderData()
data.Data["NetworkingConsolePluginImage"] = os.Getenv("NETWORKING_CONSOLE_PLUGIN_IMAGE")

manifests, err := render.RenderDir(filepath.Join(manifestDir, "networking-console-plugin"), &data)
if err != nil {
return nil, errors.Wrap(err, "failed to render networking-console-plugin manifests")
}
return manifests, nil
}

type Patch struct {
Type types.PatchType
Data []byte
}

// registerNetworkingConsolePlugin enables console plugin for networking-console if not already enabled
func registerNetworkingConsolePlugin(cl cnoclient.Client) error {
if !isConsolePluginCRDExist(cl) {
return nil
}
pluginName := "networking-console-plugin"
clusterConsole := "cluster"
consoleKey := client.ObjectKey{Name: "cluster"}
consoleObj := &operv1.Console{}

crc := cl.Default().CRClient()
err := crc.Get(context.TODO(), consoleKey, consoleObj)
if err != nil {
if apierrors.IsNotFound(err) {
log.Printf("NOTICE: consoles.operator.openshift.io %s is not available yet.", clusterConsole)
return nil
}
return errors.Wrapf(err, "Could not get consoles.operator.openshift.io resource")
}

if slices.Contains(consoleObj.Spec.Plugins, pluginName) {
log.Printf("NOTICE: console already contains plugin %s", pluginName)
return nil
}

var patches []cnoclient.JsonPatch

if consoleObj.Spec.Plugins == nil {
patches = []cnoclient.JsonPatch{{
Op: "add",
Path: "/spec/plugins",
Value: []string{pluginName},
}}
} else {
patches = []cnoclient.JsonPatch{{
Op: "add",
Path: "/spec/plugins/-",
Value: pluginName,
}}
}

patchBytes, err := json.Marshal(patches)
patch := crclient.RawPatch(types.JSONPatchType, patchBytes)

if err != nil {
panic(err)
}

err = crc.Patch(context.TODO(), consoleObj, patch)
if err != nil {
return errors.Wrap(err, fmt.Sprintf("registering console-plugin %q with console %q failed", pluginName, clusterConsole))
}
return nil
}

func isSupportedDualStackPlatform(platformType configv1.PlatformType) bool {
return dualStackPlatforms.Has(string(platformType))
}

func isConsolePluginCRDExist(cl cnoclient.Client) bool {
consolePluginCrdKey := client.ObjectKey{Name: "consoleplugins.console.openshift.io"}
consolePluginCrdObj := &apiextensions.CustomResourceDefinition{}
err := cl.Default().CRClient().Get(context.TODO(), consolePluginCrdKey, consolePluginCrdObj)
return err == nil
}

0 comments on commit 8aa4cb5

Please sign in to comment.