Skip to content
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

add OperatorGroup #480

Merged
merged 33 commits into from
Nov 7, 2018
Merged

Conversation

jpeeler
Copy link

@jpeeler jpeeler commented Sep 24, 2018

So far the reconcile loop only looks at the namespace selector and writes the results to the status and an annotation on each deployment.

@openshift-ci-robot openshift-ci-robot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Sep 24, 2018
@openshift-ci-robot openshift-ci-robot added the size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. label Sep 24, 2018
var b strings.Builder
nsCount := len(namespaceList.Items)
for i := 0; i < nsCount-1; i++ {
fmt.Fprintf(&b, "%v,", namespaceList.Items[i])
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might require .Name here, but maybe there's a better way to do all this in general?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you don't need to use .Name (which I think we may need to), you can use strings.Join(namespaceList.Items, ",") here as an alternative.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it makes sense for namespaces in the status to just be a list of strings. Normally when we do object references we try and include GVK but namespaces are pretty ingrained (e.g. metadata.namespace is just a string on every kube object).

If we make that change, then this part just becomes what @njhale suggested

controller-tools.k8s.io: "1.0"
name: operatorgroups.operators.coreos.com.operators.coreos.com
spec:
group: operators.coreos.com.operators.coreos.com
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this looks like a weird merge? should be operators.coreos.com

- metadata
- spec
version: v1alpha2
status:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't commit the status (it will be ingored anyway, but no reason to have it)


type OperatorGroupSpec struct {
Selector metav1.LabelSelector `json:"selector"`
ServiceAccount corev1.ServiceAccount `json:"serviceAccount"`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we want both of these to be omittempty

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason being that if the selector is not present, that all namespaces are selected by default? What account would be used in the absence of a specified service account?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, and in absence of a serviceaccount we'd use the one that OLM is running as (system:controller:operator-lifecycle-manager)

}

type OperatorGroupStatus struct {
Namespaces []corev1.Namespace `json:"namespaces"`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably want a "last updated time" here

pkg/controller/operators/olm/operator.go Outdated Show resolved Hide resolved
var b strings.Builder
nsCount := len(namespaceList.Items)
for i := 0; i < nsCount-1; i++ {
fmt.Fprintf(&b, "%v,", namespaceList.Items[i])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it makes sense for namespaces in the status to just be a list of strings. Normally when we do object references we try and include GVK but namespaces are pretty ingrained (e.g. metadata.namespace is just a string on every kube object).

If we make that change, then this part just becomes what @njhale suggested

pkg/controller/operators/olm/operator.go Show resolved Hide resolved
@jpeeler jpeeler force-pushed the add-operator-group branch 2 times, most recently from f58875a to 788d864 Compare September 27, 2018 17:54
@jpeeler
Copy link
Author

jpeeler commented Sep 27, 2018

The failing images test will pass once #489 is merged.

@jpeeler
Copy link
Author

jpeeler commented Sep 28, 2018

/test images

nsCount := len(namespaceList.Items)

if len(op.Status.Namespaces) == nsCount {
for i, v := range namespaceList.Items {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be better to implement this as a set (map[string]struct{}{}) instead of a list; I'm not sure if we get order guarantees from List


for _, deploy := range strategyDetailsDeployment.DeploymentSpecs {
deploy.Spec.Template.Annotations["olm.targetNamespaces"] = nsList.String()
_, err := a.client.Operators().ClusterServiceVersions(currentNamespace).Update(csv)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll have a better chance of this succeeding if we send a Patch update.

if err != nil {
return fmt.Errorf("CSV update for '%v' failed: %v\n", csvName, err)
}
a.requeueCSV(csvName, currentNamespace)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this will requeue the same csv multiple times if there're multiple deployments in the same csv

I'm also not sure we need to requeue - if this update causes the csv deployment to go unhealthy, we should detect that as an issue in the CSV anyway.

pkg/controller/operators/olm/operator.go Outdated Show resolved Hide resolved
}
DoUpdate:
if needsUpdate {
if err := a.updateDeploymentAnnotation(&op); err != nil {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is going to update for every single namespace that's new, I don't think we want it to be in the loop. that way you can just break the loop and don't need a label/goto

pkg/controller/operators/olm/operator.go Outdated Show resolved Hide resolved
@jpeeler jpeeler force-pushed the add-operator-group branch 3 times, most recently from 2c80629 to 1e96092 Compare October 1, 2018 17:05
return err
}
operatorGroupOpts := metav1.ListOptions{LabelSelector: selector.String()}
// TODO(jpeeler): this needs to use user impersonation with op.Spec.ServiceAccount
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: remove this comment (I don't think we'll want to use impersonation here)


nsCount := len(namespaceList.Items)

if len(op.Status.Namespaces) == nsCount {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would make sense to pull this out into a helper like namespacesChanged(clusterNamespaces, statusNamespaces) bool

op.Status.LastUpdated = timeNow()

// make string list made up of comma separated namespaces
var nsList strings.Builder
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why don't we pull out the list of namespaces as just a list of strings before we get here? then you can just strings.join() here

and actually if you you make a new type like type NamespaceNameList []string, you can implement the Stringer interface and have it call strings.join so that this reads more nicely

managerPolicyRules := []rbacv1.PolicyRule{}
apiEditPolicyRules := []rbacv1.PolicyRule{}
apiViewPolicyRules := []rbacv1.PolicyRule{}
for _, owned := range csv.Spec.CustomResourceDefinitions.Owned {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you also want to range over csv.Spec.ApiServiceDefinitions which hold descriptions of APIs provided by aggregated apiservers.

return fmt.Errorf("could not assert strategy implementation as deployment for CSV %s", csvName)
}

managerPolicyRules := []rbacv1.PolicyRule{}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the rbac generation is broadly doing the right thing, but the installplan takes care of some of this already:

  1. for any CRD it installs, it creates a
    1. <that-crd>-edit ClusterRole
    2. <that-crd>-view ClusterRole

All that's really left for this control loop to do is make sure there's an <operatorgroup>-edit and an <operatorgroup>-view ClusterRole available (which I see that you have!)

So I think most of this will remain the same, you just don't need to worry about the specific edit/view clusterroles

if err != nil {
return err
}
for _, sa := range strategyDetailsDeployment.Permissions {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These generated roles aren't for the serviceaccount for the operator to use, they're for end users and administrators.

It's so that a cluster admin can bind jpeeler to etcd-edit in namespace foo to give access to operator-provided services.

(we will need a separate thing to ensure that the serviceaccount for the operator has the correct permissions in target namespaces)

@jpeeler jpeeler force-pushed the add-operator-group branch 2 times, most recently from 5d3c426 to abc9379 Compare October 2, 2018 19:32
Reason: v1alpha1.CSVReasonCopied,
LastUpdateTime: timeNow(),
}
newCSV.Annotations["OriginalCSV"] = fmt.Sprintf("Namespace:%v, ResourceVersion:%v", csv.GetNamespace(), csv.GetResourceVersion())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 can we make this more machine readable <namespace>/<csvname>?

also we should follow the annotation key convention we used before, I think it would be olm.originalCSV?

@jpeeler jpeeler force-pushed the add-operator-group branch 3 times, most recently from 09ef2c4 to bb9d5fa Compare October 12, 2018 18:26
@jpeeler
Copy link
Author

jpeeler commented Oct 12, 2018

@ecordell I'm working on rebasing next, but I just pushed the simple e2e and associated fixes.

@jpeeler jpeeler force-pushed the add-operator-group branch 2 times, most recently from 084c6f0 to ec652c6 Compare October 15, 2018 17:35
@jpeeler jpeeler force-pushed the add-operator-group branch from f5c3a60 to 5b7d140 Compare November 1, 2018 16:05
@jpeeler
Copy link
Author

jpeeler commented Nov 1, 2018

/retest

@jpeeler
Copy link
Author

jpeeler commented Nov 1, 2018

/retest
currently timing out on yum update failures

pkg/controller/operators/olm/operator.go Outdated Show resolved Hide resolved
@jpeeler
Copy link
Author

jpeeler commented Nov 2, 2018

/retest

Looks like CI operator is having a bad day:

panic: runtime error: index out of range

goroutine 135 [running]:
github.com/openshift/ci-operator/pkg/steps.waitForPodCompletion(0x1285700, 0xc4204b55c0, 0xc4204ac330, 0xe, 0x1275cc0, 0xc4202aa2d0, 0x7ffe49a0613e, 0xf, 0x0, 0xc420859520)
	/go/src/github.com/openshift/ci-operator/pkg/steps/template.go:572 +0x3f7
github.com/openshift/ci-operator/pkg/steps.(*podStep).Run(0xc4205aa1c0, 0x1275a40, 0xc4200517c0, 0x0, 0x5, 0xc42036a400)
	/go/src/github.com/openshift/ci-operator/pkg/steps/test.go:120 +0xc4f
github.com/openshift/ci-operator/pkg/steps/release.(*assembleReleaseStep).Run(0xc4204315e0, 0x1275a40, 0xc4200517c0, 0xbeef49f166006400, 0x65f0f3ff12, 0x1974400)
	/go/src/github.com/openshift/ci-operator/pkg/steps/release/create_release.go:83 +0x773
github.com/openshift/ci-operator/pkg/steps.runStep(0x1275a40, 0xc4200517c0, 0xc420213140, 0xc420322f00, 0x0)
	/go/src/github.com/openshift/ci-operator/pkg/steps/run.go:105 +0x92
created by github.com/openshift/ci-operator/pkg/steps.Run
	/go/src/github.com/openshift/ci-operator/pkg/steps/run.go:71 +0x3a1```

client versioned.Interface
resolver install.StrategyResolverInterface
lister operatorlister.OperatorLister
csvLister map[string]csvlister.ClusterServiceVersionLister
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After some fixes in PR-536 get in, we can update this to extend operatorlister.OperatorLister.

njhale
njhale previously requested changes Nov 5, 2018
Copy link
Member

@njhale njhale left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great overall! A few minor things:

pkg/controller/operators/olm/operator.go Show resolved Hide resolved
@@ -21,6 +24,7 @@ import (
"k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: import ordering

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you elaborate? I just always let goimports do its thing.

Copy link
Member

@njhale njhale Nov 6, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't look split up correctly. It should be:

import(
standard packages

external stuff

internal stuff
)

From what I can see, it looks like:

import (
standard packages

internal stuff
external stuff
)

pkg/controller/operators/olm/operator.go Outdated Show resolved Hide resolved
pkg/controller/operators/olm/operator_test.go Outdated Show resolved Hide resolved
pkg/controller/operators/olm/operator_test.go Outdated Show resolved Hide resolved
pkg/controller/operators/olm/operatorgroup.go Outdated Show resolved Hide resolved
pkg/controller/operators/olm/operatorgroup.go Outdated Show resolved Hide resolved
pkg/controller/operators/olm/operatorgroup.go Show resolved Hide resolved
}
}
if k8serrors.IsAlreadyExists(err) {
fetchedCSV, err := a.client.OperatorsV1alpha1().ClusterServiceVersions(ns.Name).Get(csv.GetName(), metav1.GetOptions{})
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you check for a pre-existing CSV before attempting to create or update, you can make use of the lister to avoid making an extra API call.

Jeff Peeler added 4 commits November 6, 2018 15:48
Instead of creating operator groups in a "second phase", create the
resources at the same time along with everything else. This removes a
small amount of namespace specific code from NewFakeOperator and makes
things more consistent.
return error as the last argument
This is already handled in a more clear way in removeDanglingChildCSVs.
Essentially, optimize for the update case rather than create since
creates only happen once.
spec:
properties:
selector:
type: object
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

}

type OperatorGroupStatus struct {
Namespaces []*corev1.Namespace `json:"namespaces"`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm still a little concerned that this could get too long. []string seems slightly safer. Perhaps the real answer is to wait for CRDs to support arbitrary subresources and implement a /namespaces subresource (so that we can paginate)

_, err := opClientFake.KubernetesInterface().CoreV1().Namespaces().Create(&v1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: namespace}})
if err != nil {
return nil, err
for _, ns := range namespaces {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not a big deal, but if you're passing the objects in like this you can just append the namespaces to k8sObjs and they'll exist in the fake for testing. or you can remove the explicit namespaces param and build the object list in the tests

@jpeeler
Copy link
Author

jpeeler commented Nov 7, 2018

/test e2e-aws-olm

@ecordell
Copy link
Member

ecordell commented Nov 7, 2018

/approve
/lgtm

@openshift-ci-robot openshift-ci-robot added the lgtm Indicates that a PR is ready to be merged. label Nov 7, 2018
@openshift-ci-robot
Copy link
Collaborator

[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 /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-ci-robot openshift-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Nov 7, 2018
@njhale njhale dismissed their stale review November 7, 2018 14:44

to be handled follow ups

@jpeeler
Copy link
Author

jpeeler commented Nov 7, 2018

/test e2e-aws-olm

@ecordell ecordell merged commit 17359ee into operator-framework:master Nov 7, 2018
ecordell added a commit to ecordell/operator-lifecycle-manager that referenced this pull request Mar 8, 2019
@njhale njhale added the kind/feature Categorizes issue or PR as related to a new feature. label Mar 19, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. kind/feature Categorizes issue or PR as related to a new feature. lgtm Indicates that a PR is ready to be merged. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants