Deploy operator-lifecycle-manager (OLM), node-maintenance-operator (NMO) and constellation-node-operator

Signed-off-by: Malte Poll <mp@edgeless.systems>
This commit is contained in:
Malte Poll 2022-08-04 16:15:52 +02:00 committed by Malte Poll
parent 18a89d2881
commit 2c7129987a
23 changed files with 8756 additions and 32 deletions

View File

@ -7,10 +7,13 @@ import (
"github.com/edgelesssys/constellation/bootstrapper/internal/kubernetes/k8sapi/resources"
corev1 "k8s.io/api/core/v1"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
apiextensionsclientv1 "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/watch"
"k8s.io/cli-runtime/pkg/resource"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
@ -21,8 +24,9 @@ const fieldManager = "constellation-bootstrapper"
// Client implements k8sapi.Client interface and talks to the Kubernetes API.
type Client struct {
clientset kubernetes.Interface
builder *resource.Builder
clientset kubernetes.Interface
apiextensionClient apiextensionsclientv1.ApiextensionsV1Interface
builder *resource.Builder
}
// New creates a new Client, talking to the real k8s API.
@ -36,13 +40,18 @@ func New(config []byte) (*Client, error) {
return nil, fmt.Errorf("creating k8s client from kubeconfig: %w", err)
}
apiextensionClient, err := apiextensionsclientv1.NewForConfig(clientConfig)
if err != nil {
return nil, fmt.Errorf("creating api extension client from kubeconfig: %w", err)
}
restClientGetter, err := newRESTClientGetter(config)
if err != nil {
return nil, fmt.Errorf("creating k8s RESTClientGetter from kubeconfig: %w", err)
}
builder := resource.NewBuilder(restClientGetter).Unstructured()
return &Client{clientset: clientset, builder: builder}, nil
return &Client{clientset: clientset, apiextensionClient: apiextensionClient, builder: builder}, nil
}
// ApplyOneObject uses server-side apply to send unstructured JSON blobs to the server and let it handle the core logic.
@ -147,3 +156,37 @@ func (c *Client) AddNodeSelectorsToDeployment(ctx context.Context, selectors map
}
return nil
}
// WaitForCRD waits for the given CRD to be established.
func (c *Client) WaitForCRD(ctx context.Context, crd string) error {
watcher, err := c.apiextensionClient.CustomResourceDefinitions().Watch(ctx, metav1.ListOptions{
FieldSelector: fmt.Sprintf("metadata.name=%s", crd),
})
if err != nil {
return err
}
defer watcher.Stop()
for event := range watcher.ResultChan() {
switch event.Type {
case watch.Added, watch.Modified:
crd := event.Object.(*apiextensionsv1.CustomResourceDefinition)
if crdHasCondition(crd.Status.Conditions, apiextensionsv1.Established) {
return nil
}
case watch.Deleted:
return fmt.Errorf("crd %q deleted", crd)
case watch.Error:
return fmt.Errorf("crd %q error: %v", crd, event.Object)
}
}
return fmt.Errorf("crd %q not established", crd)
}
func crdHasCondition(conditions []apiextensionsv1.CustomResourceDefinitionCondition, conditionType apiextensionsv1.CustomResourceDefinitionConditionType) bool {
for _, condition := range conditions {
if condition.Type == conditionType && condition.Status == apiextensionsv1.ConditionTrue {
return true
}
}
return false
}

View File

@ -16,12 +16,15 @@ import (
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
k8s "k8s.io/api/core/v1"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
apiextensionsclientv1 "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/api/meta/testrestmapper"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/serializer/json"
"k8s.io/apimachinery/pkg/watch"
"k8s.io/cli-runtime/pkg/resource"
"k8s.io/client-go/kubernetes/fake"
"k8s.io/client-go/kubernetes/scheme"
@ -376,3 +379,104 @@ func TestAddNodeSelectorsToDeployment(t *testing.T) {
})
}
}
func TestWaitForCRD(t *testing.T) {
testCases := map[string]struct {
crd string
events []watch.Event
watchErr error
wantErr bool
}{
"Success": {
crd: "test-crd",
events: []watch.Event{
{
Type: watch.Added,
Object: &apiextensionsv1.CustomResourceDefinition{
Status: apiextensionsv1.CustomResourceDefinitionStatus{
Conditions: []apiextensionsv1.CustomResourceDefinitionCondition{
{
Type: apiextensionsv1.Established,
Status: apiextensionsv1.ConditionTrue,
},
},
},
},
},
},
},
"watch error": {
crd: "test-crd",
watchErr: errors.New("watch error"),
wantErr: true,
},
"crd deleted": {
crd: "test-crd",
events: []watch.Event{{Type: watch.Deleted}},
wantErr: true,
},
"other error": {
crd: "test-crd",
events: []watch.Event{{Type: watch.Error}},
wantErr: true,
},
}
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
assert := assert.New(t)
require := require.New(t)
client := Client{
apiextensionClient: &stubCRDWatcher{events: tc.events, watchErr: tc.watchErr},
}
err := client.WaitForCRD(context.Background(), tc.crd)
if tc.wantErr {
assert.Error(err)
return
}
require.NoError(err)
})
}
}
type stubCRDWatcher struct {
events []watch.Event
watchErr error
apiextensionsclientv1.ApiextensionsV1Interface
}
func (w *stubCRDWatcher) CustomResourceDefinitions() apiextensionsclientv1.CustomResourceDefinitionInterface {
return &stubCustomResourceDefinitions{
events: w.events,
watchErr: w.watchErr,
}
}
type stubCustomResourceDefinitions struct {
events []watch.Event
watchErr error
apiextensionsclientv1.CustomResourceDefinitionInterface
}
func (c *stubCustomResourceDefinitions) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) {
eventChan := make(chan watch.Event, len(c.events))
for _, event := range c.events {
eventChan <- event
}
return &stubCRDWatch{events: eventChan}, c.watchErr
}
type stubCRDWatch struct {
events chan watch.Event
}
func (w *stubCRDWatch) Stop() {
close(w.events)
}
func (w *stubCRDWatch) ResultChan() <-chan watch.Event {
return w.events
}

View File

@ -22,6 +22,8 @@ type Client interface {
CreateConfigMap(ctx context.Context, configMap corev1.ConfigMap) error
AddTolerationsToDeployment(ctx context.Context, tolerations []corev1.Toleration, name string, namespace string) error
AddNodeSelectorsToDeployment(ctx context.Context, selectors map[string]string, name string, namespace string) error
// WaitForCRD waits for the given CRD to be established.
WaitForCRD(ctx context.Context, crd string) error
}
// clientGenerator can generate new clients from a kubeconfig.
@ -111,3 +113,19 @@ func (k *Kubectl) AddNodeSelectorsToDeployment(ctx context.Context, selectors ma
return nil
}
// WaitForCRD waits for a list of CRDs to be established.
func (k *Kubectl) WaitForCRDs(ctx context.Context, crds []string) error {
client, err := k.clientGenerator.NewClient(k.kubeconfig)
if err != nil {
return err
}
for _, crd := range crds {
err = client.WaitForCRD(ctx, crd)
if err != nil {
return err
}
}
return nil
}

View File

@ -23,6 +23,7 @@ type stubClient struct {
createConfigMapErr error
addTolerationsToDeploymentErr error
addNodeSelectorToDeploymentErr error
waitForCRDErr error
}
func (s *stubClient) ApplyOneObject(info *resource.Info, forceConflicts bool) error {
@ -53,16 +54,22 @@ type stubClientGenerator struct {
createConfigMapErr error
addTolerationsToDeploymentErr error
addNodeSelectorToDeploymentErr error
waitForCRDErr error
}
func (s *stubClient) WaitForCRD(ctx context.Context, crd string) error {
return s.waitForCRDErr
}
func (s *stubClientGenerator) NewClient(kubeconfig []byte) (Client, error) {
return &stubClient{
s.applyOneObjectErr,
s.getObjectsInfos,
s.getObjectsErr,
s.createConfigMapErr,
s.addTolerationsToDeploymentErr,
s.addNodeSelectorToDeploymentErr,
applyOneObjectErr: s.applyOneObjectErr,
getObjectsInfos: s.getObjectsInfos,
getObjectsErr: s.getObjectsErr,
createConfigMapErr: s.createConfigMapErr,
addTolerationsToDeploymentErr: s.addTolerationsToDeploymentErr,
addNodeSelectorToDeploymentErr: s.addNodeSelectorToDeploymentErr,
waitForCRDErr: s.waitForCRDErr,
}, s.newClientErr
}

View File

@ -10,6 +10,8 @@ import (
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
const accessManagerNamespace = "kube-system"
// accessManagerDeployment holds the configuration for the SSH user creation pods. User/Key definitions are stored in the ConfigMap, and the manager is deployed on each node by the DaemonSet.
type accessManagerDeployment struct {
ConfigMap k8s.ConfigMap
@ -35,7 +37,7 @@ func NewAccessManagerDeployment(sshUsers map[string]string) *accessManagerDeploy
"app.kubernetes.io/managed-by": "Constellation",
},
Name: "constellation-access-manager",
Namespace: "kube-system",
Namespace: accessManagerNamespace,
},
AutomountServiceAccountToken: proto.Bool(true),
},
@ -46,7 +48,7 @@ func NewAccessManagerDeployment(sshUsers map[string]string) *accessManagerDeploy
},
ObjectMeta: v1.ObjectMeta{
Name: "ssh-users",
Namespace: "kube-system",
Namespace: accessManagerNamespace,
},
Data: sshUsers,
},
@ -57,7 +59,7 @@ func NewAccessManagerDeployment(sshUsers map[string]string) *accessManagerDeploy
},
ObjectMeta: v1.ObjectMeta{
Name: "constellation-access-manager",
Namespace: "kube-system",
Namespace: accessManagerNamespace,
Labels: map[string]string{
"app.kubernetes.io/instance": "constellation",
"app.kubernetes.io/name": "constellation-access-manager",
@ -148,7 +150,7 @@ func NewAccessManagerDeployment(sshUsers map[string]string) *accessManagerDeploy
"app.kubernetes.io/managed-by": "Constellation",
},
Name: "constellation-access-manager",
Namespace: "kube-system",
Namespace: accessManagerNamespace,
},
Rules: []rbac.PolicyRule{
{
@ -177,7 +179,7 @@ func NewAccessManagerDeployment(sshUsers map[string]string) *accessManagerDeploy
"app.kubernetes.io/managed-by": "Constellation",
},
Name: "constellation-access-manager",
Namespace: "kube-system",
Namespace: accessManagerNamespace,
},
RoleRef: rbac.RoleRef{
APIGroup: "rbac.authorization.k8s.io",
@ -188,11 +190,11 @@ func NewAccessManagerDeployment(sshUsers map[string]string) *accessManagerDeploy
{
Kind: "ServiceAccount",
Name: "constellation-access-manager",
Namespace: "kube-system",
Namespace: accessManagerNamespace,
},
},
},
ImagePullSecret: NewImagePullSecret(),
ImagePullSecret: NewImagePullSecret(accessManagerNamespace),
}
}

View File

@ -10,7 +10,7 @@ import (
)
// NewImagePullSecret creates a new k8s.Secret from the config for authenticating when pulling images.
func NewImagePullSecret() k8s.Secret {
func NewImagePullSecret(namespace string) k8s.Secret {
base64EncodedSecret := base64.StdEncoding.EncodeToString(
[]byte(fmt.Sprintf("%s:%s", secrets.PullSecretUser, secrets.PullSecretToken)),
)
@ -24,7 +24,7 @@ func NewImagePullSecret() k8s.Secret {
},
ObjectMeta: meta.ObjectMeta{
Name: secrets.PullSecretName,
Namespace: "kube-system",
Namespace: namespace,
},
StringData: map[string]string{".dockerconfigjson": pullSecretDockerCfgJSON},
Type: "kubernetes.io/dockerconfigjson",

View File

@ -7,7 +7,8 @@ import (
)
func TestImagePullSecret(t *testing.T) {
imgPullSec := NewImagePullSecret()
imgPullSec := NewImagePullSecret("namespace")
_, err := imgPullSec.Marshal()
assert.NoError(t, err)
assert.Equal(t, "namespace", imgPullSec.Namespace)
}

View File

@ -13,6 +13,8 @@ import (
"k8s.io/apimachinery/pkg/util/intstr"
)
const kmsNamespace = "kube-system"
type kmsDeployment struct {
ServiceAccount k8s.ServiceAccount
Service k8s.Service
@ -43,7 +45,7 @@ func NewKMSDeployment(csp string, config KMSConfig) *kmsDeployment {
},
ObjectMeta: meta.ObjectMeta{
Name: "kms",
Namespace: "kube-system",
Namespace: kmsNamespace,
},
},
Service: k8s.Service{
@ -53,7 +55,7 @@ func NewKMSDeployment(csp string, config KMSConfig) *kmsDeployment {
},
ObjectMeta: meta.ObjectMeta{
Name: "kms",
Namespace: "kube-system",
Namespace: kmsNamespace,
},
Spec: k8s.ServiceSpec{
Type: k8s.ServiceTypeClusterIP,
@ -106,7 +108,7 @@ func NewKMSDeployment(csp string, config KMSConfig) *kmsDeployment {
{
Kind: "ServiceAccount",
Name: "kms",
Namespace: "kube-system",
Namespace: kmsNamespace,
},
},
},
@ -120,7 +122,7 @@ func NewKMSDeployment(csp string, config KMSConfig) *kmsDeployment {
"k8s-app": "kms",
},
Name: "kms",
Namespace: "kube-system",
Namespace: kmsNamespace,
},
Spec: apps.DeploymentSpec{
Selector: &meta.LabelSelector{
@ -239,7 +241,7 @@ func NewKMSDeployment(csp string, config KMSConfig) *kmsDeployment {
},
ObjectMeta: meta.ObjectMeta{
Name: constants.ConstellationMasterSecretStoreName,
Namespace: "kube-system",
Namespace: kmsNamespace,
},
Data: map[string][]byte{
constants.ConstellationMasterSecretKey: config.MasterSecret,
@ -247,7 +249,7 @@ func NewKMSDeployment(csp string, config KMSConfig) *kmsDeployment {
},
Type: "Opaque",
},
ImagePullSecret: NewImagePullSecret(),
ImagePullSecret: NewImagePullSecret(kmsNamespace),
}
}

View File

@ -0,0 +1,78 @@
package resources
import (
"time"
"github.com/edgelesssys/constellation/internal/versions"
operatorsv1 "github.com/operator-framework/api/pkg/operators/v1"
operatorsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
const (
nodeMaintenanceOperatorNamespace = "kube-system"
nodeMaintenanceOperatorCatalogNamespace = "olm"
)
type nodeMaintenanceOperatorDeployment struct {
CatalogSource operatorsv1alpha1.CatalogSource
OperatorGroup operatorsv1.OperatorGroup
Subscription operatorsv1alpha1.Subscription
}
// NewNodeMaintenanceOperatorDeployment creates a new node maintenance operator (NMO) deployment.
// See https://github.com/medik8s/node-maintenance-operator for more information.
func NewNodeMaintenanceOperatorDeployment() *nodeMaintenanceOperatorDeployment {
return &nodeMaintenanceOperatorDeployment{
CatalogSource: operatorsv1alpha1.CatalogSource{
TypeMeta: metav1.TypeMeta{APIVersion: "operators.coreos.com/v1alpha1", Kind: "CatalogSource"},
ObjectMeta: metav1.ObjectMeta{
Name: "node-maintenance-operator-catalog",
Namespace: nodeMaintenanceOperatorCatalogNamespace,
},
Spec: operatorsv1alpha1.CatalogSourceSpec{
SourceType: "grpc",
Image: versions.NodeMaintenanceOperatorCatalogImage + ":" + versions.NodeMaintenanceOperatorVersion,
DisplayName: "Node Maintenance Operator",
Publisher: "Medik8s Team",
UpdateStrategy: &operatorsv1alpha1.UpdateStrategy{
RegistryPoll: &operatorsv1alpha1.RegistryPoll{
RawInterval: "1m0s",
Interval: &metav1.Duration{
Duration: time.Minute,
},
},
},
},
},
OperatorGroup: operatorsv1.OperatorGroup{
TypeMeta: metav1.TypeMeta{APIVersion: "operators.coreos.com/v1", Kind: "OperatorGroup"},
ObjectMeta: metav1.ObjectMeta{
Name: "constellation-og",
Namespace: nodeMaintenanceOperatorNamespace,
},
Spec: operatorsv1.OperatorGroupSpec{
UpgradeStrategy: operatorsv1.UpgradeStrategyDefault,
},
},
Subscription: operatorsv1alpha1.Subscription{
TypeMeta: metav1.TypeMeta{APIVersion: "operators.coreos.com/v1alpha1", Kind: "Subscription"},
ObjectMeta: metav1.ObjectMeta{
Name: "node-maintenance-operator-sub",
Namespace: nodeMaintenanceOperatorNamespace,
},
Spec: &operatorsv1alpha1.SubscriptionSpec{
Channel: "stable",
Package: "node-maintenance-operator",
CatalogSource: "node-maintenance-operator-catalog",
CatalogSourceNamespace: "olm",
InstallPlanApproval: operatorsv1alpha1.ApprovalAutomatic,
StartingCSV: "node-maintenance-operator." + versions.NodeMaintenanceOperatorVersion,
},
},
}
}
func (c *nodeMaintenanceOperatorDeployment) Marshal() ([]byte, error) {
return MarshalK8SResources(c)
}

View File

@ -0,0 +1,21 @@
package resources
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestNodeMaintenanceOperatorMarshalUnmarshal(t *testing.T) {
require := require.New(t)
assert := assert.New(t)
nmoDepl := NewNodeMaintenanceOperatorDeployment()
data, err := nmoDepl.Marshal()
require.NoError(err)
var recreated nodeMaintenanceOperatorDeployment
require.NoError(UnmarshalK8SResources(data, &recreated))
assert.Equal(nmoDepl, &recreated)
}

View File

@ -0,0 +1,98 @@
package resources
import (
_ "embed"
"time"
"github.com/edgelesssys/constellation/internal/secrets"
"github.com/edgelesssys/constellation/internal/versions"
operatorsv1 "github.com/operator-framework/api/pkg/operators/v1"
operatorsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
const (
nodeOperatorNamespace = "kube-system"
nodeOperatorCatalogNamespace = "olm"
)
// NodeOperatorCRDNames are the names of the custom resource definitions that are used by the node operator.
var NodeOperatorCRDNames = []string{
"autoscalingstrategies.update.edgeless.systems",
"nodeimages.update.edgeless.systems",
"pendingnodes.update.edgeless.systems",
"scalinggroups.update.edgeless.systems",
}
type nodeOperatorDeployment struct {
CatalogSource operatorsv1alpha1.CatalogSource
OperatorGroup operatorsv1.OperatorGroup
Subscription operatorsv1alpha1.Subscription
CatalogPullSecret corev1.Secret
ImagePullSecret corev1.Secret
}
// NewNodeOperatorDeployment creates a new constellation node operator deployment.
// See /operators/constellation-node-operator for more information.
func NewNodeOperatorDeployment(cloudProvider string, uid string) *nodeOperatorDeployment {
return &nodeOperatorDeployment{
CatalogSource: operatorsv1alpha1.CatalogSource{
TypeMeta: metav1.TypeMeta{APIVersion: "operators.coreos.com/v1alpha1", Kind: "CatalogSource"},
ObjectMeta: metav1.ObjectMeta{
Name: "constellation-node-operator-catalog",
Namespace: nodeOperatorCatalogNamespace,
},
Spec: operatorsv1alpha1.CatalogSourceSpec{
SourceType: "grpc",
Secrets: []string{secrets.PullSecretName},
Image: versions.NodeOperatorCatalogImage + ":" + versions.NodeOperatorVersion,
DisplayName: "Constellation Node Operator",
Publisher: "Edgeless Systems",
UpdateStrategy: &operatorsv1alpha1.UpdateStrategy{
RegistryPoll: &operatorsv1alpha1.RegistryPoll{
RawInterval: "1m0s",
Interval: &metav1.Duration{Duration: 1 * time.Minute},
},
},
},
},
OperatorGroup: operatorsv1.OperatorGroup{
TypeMeta: metav1.TypeMeta{APIVersion: "operators.coreos.com/v1", Kind: "OperatorGroup"},
ObjectMeta: metav1.ObjectMeta{
Name: "constellation-og",
Namespace: nodeOperatorNamespace,
},
Spec: operatorsv1.OperatorGroupSpec{
UpgradeStrategy: operatorsv1.UpgradeStrategyDefault,
},
},
Subscription: operatorsv1alpha1.Subscription{
TypeMeta: metav1.TypeMeta{APIVersion: "operators.coreos.com/v1alpha1", Kind: "Subscription"},
ObjectMeta: metav1.ObjectMeta{
Name: "constellation-node-operator-sub",
Namespace: nodeOperatorNamespace,
},
Spec: &operatorsv1alpha1.SubscriptionSpec{
Channel: "alpha",
Package: "node-operator",
CatalogSource: "constellation-node-operator-catalog",
CatalogSourceNamespace: "olm",
InstallPlanApproval: operatorsv1alpha1.ApprovalAutomatic,
StartingCSV: "node-operator." + versions.NodeOperatorVersion,
Config: &operatorsv1alpha1.SubscriptionConfig{
Env: []corev1.EnvVar{
{Name: "CONSTEL_CSP", Value: cloudProvider},
{Name: "constellation-uid", Value: uid},
},
},
},
},
CatalogPullSecret: NewImagePullSecret(nodeOperatorCatalogNamespace),
ImagePullSecret: NewImagePullSecret(nodeOperatorNamespace),
}
}
func (c *nodeOperatorDeployment) Marshal() ([]byte, error) {
return MarshalK8SResources(c)
}

View File

@ -0,0 +1,21 @@
package resources
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestNodeOperatorMarshalUnmarshal(t *testing.T) {
require := require.New(t)
assert := assert.New(t)
nmoDepl := NewNodeOperatorDeployment("csp", "uid")
data, err := nmoDepl.Marshal()
require.NoError(err)
var recreated nodeOperatorDeployment
require.NoError(UnmarshalK8SResources(data, &recreated))
assert.Equal(nmoDepl, &recreated)
}

View File

@ -0,0 +1,31 @@
package resources
import "github.com/edgelesssys/constellation/internal/crds"
// OLMCRDNames are the names of the custom resource definitions that are used by the olm operator.
var OLMCRDNames = []string{
"catalogsources.operators.coreos.com",
"clusterserviceversions.operators.coreos.com",
"installplans.operators.coreos.com",
"olmconfigs.operators.coreos.com",
"operatorconditions.operators.coreos.com",
"operatorgroups.operators.coreos.com",
"operators.operators.coreos.com",
"subscriptions.operators.coreos.com",
}
// OperatorLifecycleManagerCRDs contains custom resource definitions used by the olm operator.
type OperatorLifecycleManagerCRDs struct{}
// Marshal returns the already marshalled CRDs.
func (m *OperatorLifecycleManagerCRDs) Marshal() ([]byte, error) {
return crds.OLMCRDs, nil
}
// OperatorLifecycleManager is the deployment of the olm operator.
type OperatorLifecycleManager struct{}
// Marshal returns the already marshalled deployment yaml.
func (m *OperatorLifecycleManager) Marshal() ([]byte, error) {
return crds.OLM, nil
}

View File

@ -36,6 +36,8 @@ const (
kubeConfig = "/etc/kubernetes/admin.conf"
// kubeletStartTimeout is the maximum time given to the kubelet service to (re)start.
kubeletStartTimeout = 10 * time.Minute
// crdTimeout is the maximum time given to the CRDs to be created.
crdTimeout = 15 * time.Second
)
var providerIDRegex = regexp.MustCompile(`^azure:///subscriptions/([^/]+)/resourceGroups/([^/]+)/providers/Microsoft.Compute/virtualMachineScaleSets/([^/]+)/virtualMachines/([^/]+)$`)
@ -47,6 +49,7 @@ type Client interface {
CreateConfigMap(ctx context.Context, configMap corev1.ConfigMap) error
AddTolerationsToDeployment(ctx context.Context, tolerations []corev1.Toleration, name string, namespace string) error
AddNodeSelectorsToDeployment(ctx context.Context, selectors map[string]string, name string, namespace string) error
WaitForCRDs(ctx context.Context, crds []string) error
}
type installer interface {
@ -366,6 +369,26 @@ func (k *KubernetesUtil) SetupVerificationService(kubectl Client, verificationSe
return kubectl.Apply(verificationServiceConfiguration, true)
}
func (k *KubernetesUtil) SetupOperatorLifecycleManager(ctx context.Context, kubectl Client, olmCRDs, olmConfiguration resources.Marshaler, crdNames []string) error {
if err := kubectl.Apply(olmCRDs, true); err != nil {
return fmt.Errorf("applying OLM CRDs: %w", err)
}
crdReadyTimeout, cancel := context.WithTimeout(ctx, crdTimeout)
defer cancel()
if err := kubectl.WaitForCRDs(crdReadyTimeout, crdNames); err != nil {
return fmt.Errorf("waiting for OLM CRDs: %w", err)
}
return kubectl.Apply(olmConfiguration, true)
}
func (k *KubernetesUtil) SetupNodeMaintenanceOperator(kubectl Client, nodeMaintenanceOperatorConfiguration resources.Marshaler) error {
return kubectl.Apply(nodeMaintenanceOperatorConfiguration, true)
}
func (k *KubernetesUtil) SetupNodeOperator(ctx context.Context, kubectl Client, nodeOperatorConfiguration resources.Marshaler) error {
return kubectl.Apply(nodeOperatorConfiguration, true)
}
// JoinCluster joins existing Kubernetes cluster using kubeadm join.
func (k *KubernetesUtil) JoinCluster(ctx context.Context, joinConfig []byte, log *logger.Logger) error {
// TODO: audit policy should be user input

View File

@ -23,6 +23,9 @@ type clusterUtil interface {
SetupKMS(kubectl k8sapi.Client, kmsConfiguration resources.Marshaler) error
SetupVerificationService(kubectl k8sapi.Client, verificationServiceConfiguration resources.Marshaler) error
SetupGCPGuestAgent(kubectl k8sapi.Client, gcpGuestAgentConfiguration resources.Marshaler) error
SetupOperatorLifecycleManager(ctx context.Context, kubectl k8sapi.Client, olmCRDs, olmConfiguration resources.Marshaler, crdNames []string) error
SetupNodeMaintenanceOperator(kubectl k8sapi.Client, nodeMaintenanceOperatorConfiguration resources.Marshaler) error
SetupNodeOperator(ctx context.Context, kubectl k8sapi.Client, nodeOperatorConfiguration resources.Marshaler) error
StartKubelet() error
RestartKubelet() error
FixCilium(nodeNameK8s string, log *logger.Logger)

View File

@ -207,6 +207,13 @@ func (k *KubeWrapper) InitCluster(
return nil, fmt.Errorf("failed to setup verification service: %w", err)
}
// TODO: enable operator deployment on kubernetes 1.24 once https://github.com/medik8s/node-maintenance-operator/issues/49 is fixed
if k8sVersion != versions.V1_24 {
if err := k.setupOperators(ctx); err != nil {
return nil, fmt.Errorf("setting up operators: %w", err)
}
}
if k.cloudProvider == "gcp" {
if err := k.clusterUtil.SetupGCPGuestAgent(k.client, resources.NewGCPGuestAgentDaemonset()); err != nil {
return nil, fmt.Errorf("failed to setup gcp guest agent: %w", err)
@ -387,6 +394,28 @@ func (k *KubeWrapper) setupK8sVersionConfigMap(ctx context.Context, k8sVersion v
return nil
}
// setupOperators deploys the operator lifecycle manager and subscriptions to operators.
func (k *KubeWrapper) setupOperators(ctx context.Context) error {
if err := k.clusterUtil.SetupOperatorLifecycleManager(ctx, k.client, &resources.OperatorLifecycleManagerCRDs{}, &resources.OperatorLifecycleManager{}, resources.OLMCRDNames); err != nil {
return fmt.Errorf("setting up OLM: %w", err)
}
if err := k.clusterUtil.SetupNodeMaintenanceOperator(k.client, resources.NewNodeMaintenanceOperatorDeployment()); err != nil {
return fmt.Errorf("setting up node maintenance operator: %w", err)
}
uid, err := k.providerMetadata.UID(ctx)
if err != nil {
return fmt.Errorf("retrieving constellation UID: %w", err)
}
if err := k.clusterUtil.SetupNodeOperator(ctx, k.client, resources.NewNodeOperatorDeployment(k.cloudProvider, uid)); err != nil {
return fmt.Errorf("setting up constellation node operator: %w", err)
}
return nil
}
// manuallySetLoadbalancerIP sets the loadbalancer IP of the first control plane during init.
// The GCP guest agent does this usually, but is deployed in the cluster that doesn't exist
// at this point. This is a workaround to set the loadbalancer IP manually, so kubeadm and kubelet

View File

@ -513,6 +513,9 @@ type stubClusterUtil struct {
setupAccessManagerError error
setupVerificationServiceErr error
setupGCPGuestAgentErr error
setupOLMErr error
setupNMOErr error
setupNodeOperatorErr error
joinClusterErr error
startKubeletErr error
restartKubeletErr error
@ -566,6 +569,18 @@ func (s *stubClusterUtil) SetupVerificationService(kubectl k8sapi.Client, verifi
return s.setupVerificationServiceErr
}
func (s *stubClusterUtil) SetupOperatorLifecycleManager(ctx context.Context, kubectl k8sapi.Client, olmCRDs, olmConfiguration resources.Marshaler, crdNames []string) error {
return s.setupOLMErr
}
func (s *stubClusterUtil) SetupNodeMaintenanceOperator(kubectl k8sapi.Client, nodeMaintenanceOperatorConfiguration resources.Marshaler) error {
return s.setupNMOErr
}
func (s *stubClusterUtil) SetupNodeOperator(ctx context.Context, kubectl k8sapi.Client, nodeOperatorConfiguration resources.Marshaler) error {
return s.setupNodeOperatorErr
}
func (s *stubClusterUtil) JoinCluster(ctx context.Context, joinConfig []byte, log *logger.Logger) error {
s.joinConfigs = append(s.joinConfigs, joinConfig)
return s.joinClusterErr
@ -607,6 +622,7 @@ type stubKubectl struct {
createConfigMapErr error
AddTolerationsToDeploymentErr error
AddTNodeSelectorsToDeploymentErr error
waitForCRDsErr error
resources []resources.Marshaler
kubeconfigs [][]byte
@ -633,6 +649,10 @@ func (s *stubKubectl) AddNodeSelectorsToDeployment(ctx context.Context, selector
return s.AddTNodeSelectorsToDeploymentErr
}
func (s *stubKubectl) WaitForCRDs(ctx context.Context, crds []string) error {
return s.waitForCRDsErr
}
type stubKubeconfigReader struct {
Kubeconfig []byte
ReadErr error

8
go.mod
View File

@ -94,6 +94,7 @@ require (
google.golang.org/protobuf v1.28.0
gopkg.in/yaml.v3 v3.0.1
k8s.io/api v0.24.0
k8s.io/apiextensions-apiserver v0.24.0
k8s.io/apimachinery v0.24.0
k8s.io/apiserver v0.24.0
k8s.io/cli-runtime v0.24.0
@ -106,6 +107,11 @@ require (
k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9
)
require (
github.com/blang/semver/v4 v4.0.0 // indirect
sigs.k8s.io/controller-runtime v0.12.1 // indirect
)
require (
github.com/google/go-containerregistry v0.10.0 // indirect
go.opentelemetry.io/otel/trace v1.3.0 // indirect
@ -193,9 +199,9 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/onsi/ginkgo v1.16.5 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.0.3-0.20220114050600-8b9d41f48198 // indirect
github.com/operator-framework/api v0.15.0
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect

8
go.sum
View File

@ -317,6 +317,7 @@ github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqO
github.com/bkielbasa/cyclop v1.2.0/go.mod h1:qOI0yy6A7dYC4Zgsa72Ppm9kONl0RoIlPbzot9mhmeI=
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb/go.mod h1:PkYb9DJNAwrSvRx5DYA+gUcOIgTGVMNkfSCbZM8cWpI=
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
github.com/blizzy78/varnamelen v0.3.0/go.mod h1:hbwRdBvoBqxk34XyQ6HA0UH3G0/1TKuv5AC4eaBT0Ec=
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
@ -1126,7 +1127,6 @@ github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
@ -1136,6 +1136,7 @@ github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1y
github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
@ -1157,6 +1158,8 @@ github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxS
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
github.com/operator-framework/api v0.15.0 h1:4f9i0drtqHj7ykLoHxv92GR43S7MmQHhmFQkfm5YaGI=
github.com/operator-framework/api v0.15.0/go.mod h1:scnY9xqSeCsOdtJtNoHIXd7OtHZ14gj1hkDA4+DlgLY=
github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw=
github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE=
github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs=
@ -2301,6 +2304,7 @@ honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9
honnef.co/go/tools v0.2.1/go.mod h1:lPVVZ2BS5TfnjLyizF7o7hv7j9/L+8cZY2hLyjP9cGY=
k8s.io/api v0.24.0 h1:J0hann2hfxWr1hinZIDefw7Q96wmCBx6SSB8IY0MdDg=
k8s.io/api v0.24.0/go.mod h1:5Jl90IUrJHUJYEMANRURMiVvJ0g7Ax7r3R1bqO8zx8I=
k8s.io/apiextensions-apiserver v0.24.0 h1:JfgFqbA8gKJ/uDT++feAqk9jBIwNnL9YGdQvaI9DLtY=
k8s.io/apiextensions-apiserver v0.24.0/go.mod h1:iuVe4aEpe6827lvO6yWQVxiPSpPoSKVjkq+MIdg84cM=
k8s.io/apimachinery v0.24.0 h1:ydFCyC/DjCvFCHK5OPMKBlxayQytB8pxy8YQInd5UyQ=
k8s.io/apimachinery v0.24.0/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM=
@ -2366,6 +2370,8 @@ rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.30/go.mod h1:fEO7lRTdivWO2qYVCVG7dEADOMo/MLDCVr8So2g88Uw=
sigs.k8s.io/controller-runtime v0.12.1 h1:4BJY01xe9zKQti8oRjj/NeHKRXthf1YkYJAgLONFFoI=
sigs.k8s.io/controller-runtime v0.12.1/go.mod h1:BKhxlA4l7FPK4AQcsuL4X6vZeWnKDXez/vp1Y8dxTU0=
sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 h1:kDi4JBNAsJWfz1aEXhO8Jg87JJaPNLh5tIzYHgStQ9Y=
sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2/go.mod h1:B+TnT182UBxE84DiCz4CVE26eOSDAeYCpfDnC2kdKMY=
sigs.k8s.io/kustomize/api v0.11.4 h1:/0Mr3kfBBNcNPOW5Qwk/3eb8zkswCwnqQxxKtmrTkRo=

10
internal/crds/crds.go Normal file
View File

@ -0,0 +1,10 @@
package crds
import _ "embed"
var (
//go:embed olmCRDs.yaml
OLMCRDs []byte
//go:embed olmDeployment.yaml
OLM []byte
)

7858
internal/crds/olmCRDs.yaml Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,339 @@
# source: https://github.com/operator-framework/operator-lifecycle-manager/releases/download/v0.21.2/olm.yaml
# vendored here to allow use of goembed
---
apiVersion: v1
kind: Namespace
metadata:
name: olm
---
apiVersion: v1
kind: Namespace
metadata:
name: operators
---
kind: ServiceAccount
apiVersion: v1
metadata:
name: olm-operator-serviceaccount
namespace: olm
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: system:controller:operator-lifecycle-manager
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["*"]
- nonResourceURLs: ["*"]
verbs: ["*"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: olm-operator-binding-olm
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:controller:operator-lifecycle-manager
subjects:
- kind: ServiceAccount
name: olm-operator-serviceaccount
namespace: olm
---
apiVersion: operators.coreos.com/v1
kind: OLMConfig
metadata:
name: cluster
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: olm-operator
namespace: olm
labels:
app: olm-operator
spec:
strategy:
type: RollingUpdate
replicas: 1
selector:
matchLabels:
app: olm-operator
template:
metadata:
labels:
app: olm-operator
spec:
serviceAccountName: olm-operator-serviceaccount
containers:
- name: olm-operator
command:
- /bin/olm
args:
- --namespace
- $(OPERATOR_NAMESPACE)
- --writeStatusName
- ""
image: quay.io/operator-framework/olm@sha256:32db73274863b08cef237d02314a9d8c827ed2f33f0b00166dd3b055af63bb31
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
name: metrics
livenessProbe:
httpGet:
path: /healthz
port: 8080
scheme: HTTP
readinessProbe:
httpGet:
path: /healthz
port: 8080
scheme: HTTP
terminationMessagePolicy: FallbackToLogsOnError
env:
- name: OPERATOR_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: OPERATOR_NAME
value: olm-operator
resources:
requests:
cpu: 10m
memory: 160Mi
nodeSelector:
kubernetes.io/os: linux
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: catalog-operator
namespace: olm
labels:
app: catalog-operator
spec:
strategy:
type: RollingUpdate
replicas: 1
selector:
matchLabels:
app: catalog-operator
template:
metadata:
labels:
app: catalog-operator
spec:
serviceAccountName: olm-operator-serviceaccount
containers:
- name: catalog-operator
command:
- /bin/catalog
args:
- '--namespace'
- olm
- --configmapServerImage=quay.io/operator-framework/configmap-operator-registry:latest
- --util-image
- quay.io/operator-framework/olm@sha256:32db73274863b08cef237d02314a9d8c827ed2f33f0b00166dd3b055af63bb31
image: quay.io/operator-framework/olm@sha256:32db73274863b08cef237d02314a9d8c827ed2f33f0b00166dd3b055af63bb31
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
name: metrics
livenessProbe:
httpGet:
path: /healthz
port: 8080
scheme: HTTP
readinessProbe:
httpGet:
path: /healthz
port: 8080
scheme: HTTP
terminationMessagePolicy: FallbackToLogsOnError
resources:
requests:
cpu: 10m
memory: 80Mi
nodeSelector:
kubernetes.io/os: linux
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: aggregate-olm-edit
labels:
rbac.authorization.k8s.io/aggregate-to-admin: "true"
rbac.authorization.k8s.io/aggregate-to-edit: "true"
rules:
- apiGroups: ["operators.coreos.com"]
resources: ["subscriptions"]
verbs: ["create", "update", "patch", "delete"]
- apiGroups: ["operators.coreos.com"]
resources: ["clusterserviceversions", "catalogsources", "installplans", "subscriptions"]
verbs: ["delete"]
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: aggregate-olm-view
labels:
rbac.authorization.k8s.io/aggregate-to-admin: "true"
rbac.authorization.k8s.io/aggregate-to-edit: "true"
rbac.authorization.k8s.io/aggregate-to-view: "true"
rules:
- apiGroups: ["operators.coreos.com"]
resources: ["clusterserviceversions", "catalogsources", "installplans", "subscriptions", "operatorgroups"]
verbs: ["get", "list", "watch"]
- apiGroups: ["packages.operators.coreos.com"]
resources: ["packagemanifests", "packagemanifests/icon"]
verbs: ["get", "list", "watch"]
---
apiVersion: operators.coreos.com/v1
kind: OperatorGroup
metadata:
name: global-operators
namespace: operators
---
apiVersion: operators.coreos.com/v1
kind: OperatorGroup
metadata:
name: olm-operators
namespace: olm
spec:
targetNamespaces:
- olm
---
apiVersion: operators.coreos.com/v1alpha1
kind: ClusterServiceVersion
metadata:
name: packageserver
namespace: olm
labels:
olm.version: v0.21.2
spec:
displayName: Package Server
description: Represents an Operator package that is available from a given CatalogSource which will resolve to a ClusterServiceVersion.
minKubeVersion: 1.11.0
keywords: ['packagemanifests', 'olm', 'packages']
maintainers:
- name: Red Hat
email: openshift-operators@redhat.com
provider:
name: Red Hat
links:
- name: Package Server
url: https://github.com/operator-framework/operator-lifecycle-manager/tree/master/pkg/package-server
installModes:
- type: OwnNamespace
supported: true
- type: SingleNamespace
supported: true
- type: MultiNamespace
supported: true
- type: AllNamespaces
supported: true
install:
strategy: deployment
spec:
clusterPermissions:
- serviceAccountName: olm-operator-serviceaccount
rules:
- apiGroups:
- authorization.k8s.io
resources:
- subjectaccessreviews
verbs:
- create
- get
- apiGroups:
- ""
resources:
- configmaps
verbs:
- get
- list
- watch
- apiGroups:
- "operators.coreos.com"
resources:
- catalogsources
verbs:
- get
- list
- watch
- apiGroups:
- "packages.operators.coreos.com"
resources:
- packagemanifests
verbs:
- get
- list
deployments:
- name: packageserver
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
replicas: 2
selector:
matchLabels:
app: packageserver
template:
metadata:
labels:
app: packageserver
spec:
serviceAccountName: olm-operator-serviceaccount
nodeSelector:
kubernetes.io/os: linux
containers:
- name: packageserver
command:
- /bin/package-server
- -v=4
- --secure-port
- "5443"
- --global-namespace
- olm
image: quay.io/operator-framework/olm@sha256:32db73274863b08cef237d02314a9d8c827ed2f33f0b00166dd3b055af63bb31
imagePullPolicy: Always
ports:
- containerPort: 5443
livenessProbe:
httpGet:
scheme: HTTPS
path: /healthz
port: 5443
readinessProbe:
httpGet:
scheme: HTTPS
path: /healthz
port: 5443
terminationMessagePolicy: FallbackToLogsOnError
resources:
requests:
cpu: 10m
memory: 50Mi
securityContext:
runAsUser: 1000
volumeMounts:
- name: tmpfs
mountPath: /tmp
volumes:
- name: tmpfs
emptyDir: {}
maturity: alpha
version: v0.21.2
apiservicedefinitions:
owned:
- group: packages.operators.coreos.com
version: v1
kind: PackageManifest
name: packagemanifests
displayName: PackageManifest
description: A PackageManifest is a resource generated from existing CatalogSources and their ConfigMaps
deploymentName: packageserver
containerPort: 5443

View File

@ -30,11 +30,15 @@ func IsSupportedK8sVersion(version string) bool {
const (
// Constellation images.
// These images are built in a way that they support all versions currently listed in VersionConfigs.
JoinImage = "ghcr.io/edgelesssys/constellation/join-service:v1.4.0"
AccessManagerImage = "ghcr.io/edgelesssys/constellation/access-manager:v1.4.0"
KmsImage = "ghcr.io/edgelesssys/constellation/kmsserver:v1.4.0"
VerificationImage = "ghcr.io/edgelesssys/constellation/verification-service:v1.4.0"
GcpGuestImage = "ghcr.io/edgelesssys/gcp-guest-agent:latest"
JoinImage = "ghcr.io/edgelesssys/constellation/join-service:v1.4.0"
AccessManagerImage = "ghcr.io/edgelesssys/constellation/access-manager:v1.4.0"
KmsImage = "ghcr.io/edgelesssys/constellation/kmsserver:v1.4.0"
VerificationImage = "ghcr.io/edgelesssys/constellation/verification-service:v1.4.0"
GcpGuestImage = "ghcr.io/edgelesssys/gcp-guest-agent:latest"
NodeOperatorCatalogImage = "ghcr.io/edgelesssys/constellation/node-operator-catalog"
NodeOperatorVersion = "v1.4.1-0.20220809082533-41bdd362a18a"
NodeMaintenanceOperatorCatalogImage = "quay.io/medik8s/node-maintenance-operator-catalog"
NodeMaintenanceOperatorVersion = "v0.13.0"
// currently supported versions.
V1_22 ValidK8sVersion = "1.22"