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 AgentAction controller #73

Merged
merged 6 commits into from
Mar 11, 2022
Merged

Conversation

carolynvs
Copy link
Member

@carolynvs carolynvs commented Feb 16, 2022

I've split the installation controller in two, adding a new controller just to manage running the porter agent. The installation controller now only is responsible for creating an AgentAction resource. This triggers the AgentAction controller to make a porter agent job to execute the command from the AgentAction.

It's a bit of an extra layer of indirection but it will simplify additional controllers since they don't need to manage the porter agent job. It also enables users to request that the porter agent is run and can specify arbitrary commands, such as invoke.

Closes #39

This requires that you have porter installed from a custom build of porter with support for nonroot invocation images. The build won't pass until that PR is merged and a new tag created so we can reference it.

TODO

  • Get off of the porter fork with "reusable document types" Just embed the fields for now and we can get fancy later.
  • Fix integration test and create follow-up Fix integration test setup #76

@codecov
Copy link

codecov bot commented Feb 17, 2022

Codecov Report

Merging #73 (ca09693) into main (b87faa9) will decrease coverage by 4.06%.
The diff coverage is 65.56%.

Impacted file tree graph

@@            Coverage Diff             @@
##             main      #73      +/-   ##
==========================================
- Coverage   58.00%   53.93%   -4.07%     
==========================================
  Files           6       10       +4     
  Lines         700     1003     +303     
==========================================
+ Hits          406      541     +135     
- Misses        254      404     +150     
- Partials       40       58      +18     
Flag Coverage Δ
integration-tests ∅ <ø> (∅)
unit-tests 53.93% <65.56%> (-2.07%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
api/v1/zz_generated.deepcopy.go 0.00% <0.00%> (ø)
api/v1/installation_types.go 75.00% <50.00%> (+6.81%) ⬆️
api/v1/agentaction_types.go 66.66% <66.66%> (ø)
controllers/porter_resource.go 77.61% <77.61%> (ø)
controllers/agentaction_controller.go 79.10% <79.10%> (ø)
controllers/installation_controller.go 75.93% <80.95%> (-7.92%) ⬇️
api/v1/agentconfig_types.go 73.33% <100.00%> (ø)
api/v1/porter_resource.go 100.00% <100.00%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update b87faa9...ca09693. Read the comment docs.

Add an image reference to the manager image (which has the controllers)
to the bundle and then reference it when installing the operator.

Signed-off-by: Carolyn Van Slyck <me@carolynvanslyck.com>
@carolynvs carolynvs force-pushed the agent-controller branch 4 times, most recently from 6b2afa9 to e60c9ff Compare March 4, 2022 13:38
@@ -11,8 +11,3 @@ configMapGenerator:
- files:
- controller_manager_config.yaml
name: manager-config

images:
Copy link
Member Author

Choose a reason for hiding this comment

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

Setting the image of the controller now happens in the bundle itself so that it can use the image distributed with the bundle.

@@ -9,5 +9,7 @@ spec:
namespace: operator
name: hello
bundle:
repository: getporter/porter-hello
version: 0.1.1
repository: carolynvs/porter-hello-nonroot:v0.1.0
Copy link
Member Author

@carolynvs carolynvs Mar 4, 2022

Choose a reason for hiding this comment

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

I switched to a bundle that both takes a parameter and generates outputs to pick up on file permission problems with running as nonroot

@@ -9,5 +9,7 @@ spec:
namespace: operator
name: hello
bundle:
repository: getporter/porter-hello
version: 0.1.1
repository: ghcr.io/getporter/test/porter-hello
Copy link
Member Author

Choose a reason for hiding this comment

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

This switches to a bundle that was built with the latest nonroot changes.

feed string
version string
}{
{name: "helm3", feed: "https://mchorfa.github.io/porter-helm3/atom.xml", version: "v0.1.14"},
{name: "helm3", url: "https://github.com/carolynvs/porter-helm3/releases/download", version: "v0.1.15-8-g864f450"},
Copy link
Member Author

Choose a reason for hiding this comment

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

This is a build of helm3 that includes a patch for running in a nonroot bundle. MChorfa/porter-helm3#42 I'll submit that PR when we've fully vetted the nonroot change.

kustomize("edit", "set", "image", "manager="+img).In("config/manager").Run()
// Set the image reference in porter.yaml so that the manager image is packaged with the bundle
managerRef := resolveManagerImage()
mgx.Must(shx.Copy("installer/vanilla.porter.yaml", "installer/porter.yaml"))
Copy link
Member Author

Choose a reason for hiding this comment

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

I can't wait for this to be settable by a custom build arg! 😁

@carolynvs carolynvs added this to In Progress in Porter and Mixins via automation Mar 7, 2022
@carolynvs carolynvs marked this pull request as ready for review March 7, 2022 14:46
I've split the installation controller in two, adding a new controller
just to manage running the porter agent. The installation controller now
only is reponsible for creating an AgentAction resource. This triggers
the AgentAction controller to make a porter agent job to execute the
command from the AgentAction.

It's a bit of an extra layer of indirection but it will simplify
additional controllers since they don't need to manage the porter agent
job. It also enables users to request that the porter agent is run and
can specify arbitrary commands, such as invoke.

Signed-off-by: Carolyn Van Slyck <me@carolynvanslyck.com>
Copy link
Contributor

@bdegeeter bdegeeter left a comment

Choose a reason for hiding this comment

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

I did a manual test (by accident) with the wrong version for a bundle in an installation resource. I could not delete the resource via kubectl delete -f

Worked as expected when I fixed the version.

@@ -54,7 +54,7 @@ func (c AgentConfigSpec) GetPorterImage() string {
// We don't use a mutable tag like latest, or canary because it's a bad practice that we don't want to encourage.
// As we test out the operator with new versions of Porter, keep this value up-to-date so that the default
// version is guaranteed to work.
version = "v1.0.0-alpha.8"
version = "v1.0.0-alpha.12"
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this be set via a const in api/v1/const.go?

args: ["installation", "apply", "installation.yaml"]
files:
# base64 encoded file contents
installation.yaml: c2NoZW1hVmVyc2lvbjogMS4wLjAKbmFtZXNwYWNlOiBvcGVyYXRvcgpuYW1lOiBoZWxsbwpidW5kbGU6CiAgcmVwb3NpdG9yeTogZ2hjci5pby9nZXRwb3J0ZXIvdGVzdC9wb3J0ZXItaGVsbG8KICB2ZXJzaW9uOiAwLjIuMApwYXJhbWV0ZXJzOgogIG5hbWU6IGxsYW1hcyAK
Copy link
Contributor

Choose a reason for hiding this comment

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

I see why this needs to be base64 when creating the secret, but are we losing some usability?

I created an installation resource with an incorrect repository. I'm not able to delete the installation and an inspection of the AgentAction requires I base64 decode the installation.yaml

Copy link
Member Author

Choose a reason for hiding this comment

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

You can always delete a resource by editing it and removing any finalizers on it.

I went with base64 because it allows people to add any files they need into the working directory of the agent, without us having known about it up-front. Do you have a suggestion for how you'd like to see it done differently while still being flexible?

Copy link
Contributor

Choose a reason for hiding this comment

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

Here's a thought about the b64 encoding. The action.Spec.File data could be tested to see if it's base64. This can't be 100% accurate because some strings could meet the b64 encoding spec. For many string (like multiple line with white space, etc... a b64 encoding check will fail. Then the content can be encode for the user. This should allow a resource like this

--- 
apiVersion: porter.sh/v1
kind: AgentAction
metadata: 
  name: agentaction-sample
spec: 
  args: 
    - installation
    - apply
    - installation.yaml
  files: 
    installation.yaml: |
        schemaVersion: 1.0.0
        namespace: operator
        name: hello
        bundle:
          repository: ghcr.io/getporter/test/porter-hello
          version: 0.2.0
        parameters:
          name: llamas

Copy link
Member Author

Choose a reason for hiding this comment

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

I am concerned that it may be an indentation yaml bug generator because it isn't embedding a yaml document, it's a formatted yaml string embeded in a yaml file. Though either way it makes it much easier to introduce bugs in the document.

Since k8s users are already familiar with how to decode secrets, I am not too worried about the UX of doing exactly what secrets do for this. Let's go with following k8s existing conventions for now and if we need to revisit in later versions, I'm fine with that. I'd rather get this merged so we can try out a working operator and move forward with more controllers.

Also update the default version to alpha.13 which is the most recent
release.

Signed-off-by: Carolyn Van Slyck <me@carolynvanslyck.com>
Signed-off-by: Carolyn Van Slyck <me@carolynvanslyck.com>
Signed-off-by: Carolyn Van Slyck <me@carolynvanslyck.com>
Dockerfile Outdated
@@ -1,4 +1,4 @@
# syntax=docker/dockerfile:1.2
# syntax=docker/dockerfile-upstream:1.4.0-rc2
Copy link
Contributor

Choose a reason for hiding this comment

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

I assume that we can use the official release version now

if job == nil {
action.Status.Job = nil
action.Status.Conditions = nil
log.V(Log5Trace).Info("Cleared status because there is no current job")
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: I find it helpful to have a return statement here so that it's clear nothing should happen if no job is found

err := r.Get(ctx, types.NamespacedName{Name: "default", Namespace: operatorNamespace}, systemCfg)
if err != nil && !apierrors.IsNotFound(err) {
return porterv1.AgentConfigSpec{}, errors.Wrap(err, "cannot retrieve system level porter agent configuration")
}
Copy link
Contributor

Choose a reason for hiding this comment

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

what happens if the error is NotFound?

Copy link
Member Author

Choose a reason for hiding this comment

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

There is nothing for the controller to do. It's not an error case. I can add a comment about that.

Copy link
Member Author

Choose a reason for hiding this comment

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

Oh sorry I misunderstood which part of the code you were asking about. In this case, we are checking if there is a config defined, and using it if present. If it's not there, then that's not an error case. It just means we will use the defaults later on in that function.

},
{
Name: "JOB_VOLUME_PATH",
Value: "/porter-shared",
Copy link
Contributor

Choose a reason for hiding this comment

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

maybe it would be helpful for consistency to declare a constant for this?

Copy link
Member

@vdice vdice left a comment

Choose a reason for hiding this comment

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

Defer to @VinozzZ for final approval per outstanding feedback, otherwise LGTM

@@ -0,0 +1,40 @@
package v1

// AgentPhase are valid status of a Porter agent job
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// AgentPhase are valid status of a Porter agent job
// AgentPhase are valid statuses of a Porter agent job

api/v1/const.go Outdated

// LabelRetry is a label applied to the resources created by the
// Porter Operator, representing the retry attempt identifier. It is used to
// help the operator determine if a resource has
Copy link
Member

Choose a reason for hiding this comment

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

Looks like the comment is cut off here

err = r.uninstallInstallation(ctx, log, inst)
log.V(Log4Debug).Info("Reconciliation complete: A porter agent has been dispatched to uninstall the installation.")
return ctrl.Result{}, err
} else if isDeleted(inst) {
// This is installation without a finalizer that was deleted
// We remove the finalizer after we successfully uninstall (or someone is manually cleaning things up)
// We remove the finalizer af
Copy link
Member

Choose a reason for hiding this comment

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

This just strikes me as an odd comment break point

Signed-off-by: Carolyn Van Slyck <me@carolynvanslyck.com>
@carolynvs carolynvs merged commit 4821144 into getporter:main Mar 11, 2022
Porter and Mixins automation moved this from In Progress to Done Mar 11, 2022
@carolynvs carolynvs deleted the agent-controller branch March 11, 2022 19:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Development

Successfully merging this pull request may close these issues.

How to support invoke through the operator?
4 participants