-
Notifications
You must be signed in to change notification settings - Fork 544
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Don't process CSVs without operatorgroup #589
Don't process CSVs without operatorgroup #589
Conversation
/approve |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: ecordell The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
return | ||
} | ||
|
||
// operatorGroupForCSV returns the operatorgroup for the CSV only if the CSV is active one in the group | ||
func (a *Operator) operatorGroupForActiveCSV(logger *log.Logger, csv *v1alpha1.ClusterServiceVersion) *v1alpha2.OperatorGroup { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Function signature is a bit weird when this takes a log.Logger
argument.
@ecordell: PR needs rebase. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
@@ -391,6 +391,17 @@ func withAnnotations(obj runtime.Object, annotations map[string]string) runtime. | |||
return meta.(runtime.Object) | |||
} | |||
|
|||
func addAnnotations(annotations map[string]string, add map[string]string) map[string]string { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
1b1188c
to
7501021
Compare
/retest |
7501021
to
7667f79
Compare
/retest |
1 similar comment
/retest |
d6b9a4e
to
72ebb02
Compare
f12785d
to
e48a2c1
Compare
c360b8f
to
a0c1f69
Compare
this commit also moves the copying / rbac logic into the CSV loop, so that we don't have to requeue operatorgroups frequently
527c0ba
to
cc773f8
Compare
and aggregate them to operatorgroup clusterroles this lets us speed up the tests for operatorgroups and in the future can simplify installplan generation (can remove the clusterrole gen from installplans)
cc773f8
to
bbc68a9
Compare
/hold cancel |
namespace: {{ .Values.operator_namespace }} | ||
--- | ||
apiVersion: operators.coreos.com/v1alpha2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added an operatorgroup for the packages server, since they're required now
sa, err := c.GetServiceAccount(opGroupNamespace, perm.ServiceAccountName) | ||
require.NoError(t, err) | ||
for _, rule := range perm.Rules { | ||
satisfied, err := ruleChecker.RuleSatisfied(sa, otherNamespaceName, rule) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added a test to verify RBAC in target namespaces (kinda funky with informers in the test, but it works)
}) | ||
|
||
// validate provided API clusterroles for the operatorgroup | ||
adminRole, err := c.KubernetesInterface().RbacV1().ClusterRoles().Get(operatorGroup.Name+"-admin", metav1.GetOptions{}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This validates both that the operatorgroup clusterrole was created, and that it has correctly aggregated the csv-specific roles
@@ -286,8 +397,4 @@ func TestOperatorGroup(t *testing.T) { | |||
}) | |||
require.NoError(t, err) | |||
|
|||
err = c.KubernetesInterface().CoreV1().Namespaces().Delete(otherNamespaceName, &metav1.DeleteOptions{}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
these moved into defer
blocks further up
@@ -403,7 +404,31 @@ func (a *Operator) syncClusterServiceVersion(obj interface{}) (syncError error) | |||
"phase": clusterServiceVersion.Status.Phase, | |||
}) | |||
|
|||
operatorNamespace, ok := clusterServiceVersion.GetAnnotations()["olm.operatorNamespace"] | |||
operatorGroup := a.operatorGroupForActiveCSV(logger, clusterServiceVersion) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is the main part of the PR: gating csv processing on whether there are operatorgroups or not
@@ -429,9 +454,67 @@ func (a *Operator) syncClusterServiceVersion(obj interface{}) (syncError error) | |||
} | |||
syncError = fmt.Errorf("error transitioning ClusterServiceVersion: %s and error updating CSV status: %s", syncError, updateErr) | |||
} | |||
|
|||
// Check if we need to do any copying / annotation for the operatorgroup | |||
if err := a.copyCsvToTargetNamespace(updatedCSV, operatorGroup); err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I moved these three pieces from the operatorgroup control loop to here. The symptom was the e2e test taking a very long time (because csv changes didn't requeue their operatorgroups).
One option would've been to retrigger the owning operatorgroup on CSV change, but then in the operatorgroup side, we reach out and collect up each CSV to perform some of these actions. Moving them here removes all of that processing and lets us treat each CSV in isolation.
} | ||
|
||
// Ensure cluster roles exist for using provided apis | ||
if err := a.ensureClusterRolesForCSV(updatedCSV, operatorGroup); err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Previously we were generating operatorgroup clusterroles directly (e.g. an operatorgroup with permissions on all provided apis in the group).
To speed things up, the operatorgroup control loop just writes out a ClusterRole with aggregation rules, and each individual CSV writes out clusterroles for its provided apis with the correct label to get aggregated to the operatorgroup clusterrole. There's an e2e test to verify the aggregated roles get the correct permissions.
@@ -18,63 +17,137 @@ import ( | |||
"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/ownerutil" | |||
) | |||
|
|||
const ( | |||
operatorGroupAnnotationKey = "olm.operatorGroup" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One of us is going to have to rebase a bit. I ended up pulling this into types so the e2e can also use them in #616. Will finish reviewing this tomorrow.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think #616 will need to change (slightly) anyway - see the operatorGroupForActiveCSV
method.
return err | ||
} | ||
} | ||
log.Debug("CSV annotation completed") | ||
for _, owned := range csv.Spec.APIServiceDefinitions.Owned { | ||
namePrefix := fmt.Sprintf("%s-%s-", owned.Name, owned.Version) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is ownee.Name
always set for APIServiceDefinitions
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is not, but I want to review all of the current ones, add them, and then go make it required
in the json schema
return err | ||
} | ||
} | ||
|
||
continue | ||
} else if k8serrors.IsNotFound(err) { | ||
newCSV := csv.DeepCopy() | ||
newCSV.SetNamespace(ns) | ||
newCSV.SetResourceVersion("") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ObjectMeta.ResourceVersion
is read only so I don't think this needs to be cleared.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/lgtm
} | ||
|
||
// target namespaces don't match | ||
if annotations[operatorGroupTargetsAnnotationKey] != strings.Join(operatorGroup.Status.Namespaces, ",") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would this scenario only occur if an operator group was modified after annotations had been previously correct?
ownerutil.AddNonBlockingOwner(clusterRole, csv) | ||
existingCR, err := a.OpClient.KubernetesInterface().RbacV1().ClusterRoles().Create(clusterRole) | ||
if k8serrors.IsAlreadyExists(err) { | ||
if existingCR != nil && reflect.DeepEqual(existingCR.Labels, clusterRole.Labels) && reflect.DeepEqual(existingCR.Rules, clusterRole.Rules) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does createPatch not handle a no-op or is this just an optimization?
…v-loop Don't process CSVs without operatorgroup
This PR also moves the copying logic into the CSV control loop so that we don't have to requeue operatorgroups every time a CSV changes.
We probably shouldn't merge until there's a default operatorgroup shipping with OLM (otherwise you won't be able to install any operators)
/hold