func Convert()

in tooling/mcerepkg/internal/rukpak/convert/registryv1.go [188:342]


func Convert(in RegistryV1, installNamespace string, targetNamespaces []string) (*Plain, error) {
	if installNamespace == "" {
		installNamespace = in.CSV.Annotations["operatorframework.io/suggested-namespace"]
	}
	if installNamespace == "" {
		installNamespace = fmt.Sprintf("%s-system", in.PackageName)
	}
	supportedInstallModes := sets.New[string]()
	for _, im := range in.CSV.Spec.InstallModes {
		if im.Supported {
			supportedInstallModes.Insert(string(im.Type))
		}
	}
	if len(targetNamespaces) == 0 {
		if supportedInstallModes.Has(string(v1alpha1.InstallModeTypeAllNamespaces)) {
			targetNamespaces = []string{""}
		} else if supportedInstallModes.Has(string(v1alpha1.InstallModeTypeOwnNamespace)) {
			targetNamespaces = []string{installNamespace}
		}
	}

	if err := validateTargetNamespaces(supportedInstallModes, installNamespace, targetNamespaces); err != nil {
		return nil, err
	}

	if len(in.CSV.Spec.APIServiceDefinitions.Owned) > 0 {
		return nil, fmt.Errorf("apiServiceDefintions are not supported")
	}

	if len(in.CSV.Spec.WebhookDefinitions) > 0 {
		return nil, fmt.Errorf("webhookDefinitions are not supported")
	}

	deployments := []appsv1.Deployment{}
	serviceAccounts := map[string]corev1.ServiceAccount{}
	for _, depSpec := range in.CSV.Spec.InstallStrategy.StrategySpec.DeploymentSpecs {
		annotations := util.MergeMaps(in.CSV.Annotations, depSpec.Spec.Template.Annotations)
		annotations["olm.targetNamespaces"] = strings.Join(targetNamespaces, ",")
		deployments = append(deployments, appsv1.Deployment{
			TypeMeta: metav1.TypeMeta{
				Kind:       "Deployment",
				APIVersion: appsv1.SchemeGroupVersion.String(),
			},

			ObjectMeta: metav1.ObjectMeta{
				Namespace:   installNamespace,
				Name:        depSpec.Name,
				Labels:      depSpec.Label,
				Annotations: annotations,
			},
			Spec: depSpec.Spec,
		})
		saName := saNameOrDefault(depSpec.Spec.Template.Spec.ServiceAccountName)
		serviceAccounts[saName] = newServiceAccount(installNamespace, saName)
	}

	// NOTES:
	//   1. There's an extra Role for OperatorConditions: get/update/patch; resourceName=csv.name
	//        - This is managed by the OperatorConditions controller here: https://github.com/operator-framework/operator-lifecycle-manager/blob/9ced412f3e263b8827680dc0ad3477327cd9a508/pkg/controller/operators/operatorcondition_controller.go#L106-L109
	//   2. There's an extra RoleBinding for the above mentioned role.
	//        - Every SA mentioned in the OperatorCondition.spec.serviceAccounts is a subject for this role binding: https://github.com/operator-framework/operator-lifecycle-manager/blob/9ced412f3e263b8827680dc0ad3477327cd9a508/pkg/controller/operators/operatorcondition_controller.go#L171-L177
	//   3. strategySpec.permissions are _also_ given a clusterrole/clusterrole binding.
	//  		- (for AllNamespaces mode only?)
	//			- (where does the extra namespaces get/list/watch rule come from?)

	roles := []rbacv1.Role{}
	roleBindings := []rbacv1.RoleBinding{}
	clusterRoles := []rbacv1.ClusterRole{}
	clusterRoleBindings := []rbacv1.ClusterRoleBinding{}

	permissions := in.CSV.Spec.InstallStrategy.StrategySpec.Permissions
	clusterPermissions := in.CSV.Spec.InstallStrategy.StrategySpec.ClusterPermissions
	allPermissions := append(permissions, clusterPermissions...)

	// Create all the service accounts
	for _, permission := range allPermissions {
		saName := saNameOrDefault(permission.ServiceAccountName)
		if _, ok := serviceAccounts[saName]; !ok {
			serviceAccounts[saName] = newServiceAccount(installNamespace, saName)
		}
	}

	// If we're in AllNamespaces mode, promote the permissions to clusterPermissions
	if len(targetNamespaces) == 1 && targetNamespaces[0] == "" {
		for _, p := range permissions {
			p.Rules = append(p.Rules, rbacv1.PolicyRule{
				Verbs:     []string{"get", "list", "watch"},
				APIGroups: []string{corev1.GroupName},
				Resources: []string{"namespaces"},
			})
		}
		clusterPermissions = append(clusterPermissions, permissions...)
		permissions = nil
	}

	for _, ns := range targetNamespaces {
		for _, permission := range permissions {
			saName := saNameOrDefault(permission.ServiceAccountName)
			name, err := generateName(fmt.Sprintf("%s-%s", in.CSV.Name, saName), permission)
			if err != nil {
				return nil, err
			}
			roles = append(roles, newRole(ns, name, permission.Rules))
			roleBindings = append(roleBindings, newRoleBinding(ns, name, name, installNamespace, saName))
		}
	}

	for _, permission := range clusterPermissions {
		saName := saNameOrDefault(permission.ServiceAccountName)
		name, err := generateName(fmt.Sprintf("%s-%s", in.CSV.Name, saName), permission)
		if err != nil {
			return nil, err
		}
		clusterRoles = append(clusterRoles, newClusterRole(name, permission.Rules))
		clusterRoleBindings = append(clusterRoleBindings, newClusterRoleBinding(name, name, installNamespace, saName))
	}

	objs := []client.Object{}
	for _, obj := range serviceAccounts {
		obj := obj
		if obj.GetName() != "default" {
			objs = append(objs, &obj)
		}
	}
	for _, obj := range roles {
		obj := obj
		objs = append(objs, &obj)
	}
	for _, obj := range roleBindings {
		obj := obj
		objs = append(objs, &obj)
	}
	for _, obj := range clusterRoles {
		obj := obj
		objs = append(objs, &obj)
	}
	for _, obj := range clusterRoleBindings {
		obj := obj
		objs = append(objs, &obj)
	}
	for _, obj := range in.CRDs {
		obj := obj
		objs = append(objs, &obj)
	}
	for _, obj := range in.Others {
		obj := obj
		obj.SetNamespace(installNamespace)
		objs = append(objs, &obj)
	}
	for _, obj := range deployments {
		obj := obj
		objs = append(objs, &obj)
	}
	return &Plain{Objects: objs}, nil
}