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

Update inject to throw an error while injecting non-compliant pods #4346

Merged
merged 26 commits into from
Jun 24, 2020

Conversation

mayankshah1607
Copy link
Contributor

@mayankshah1607 mayankshah1607 commented May 7, 2020

Fixes #4214

This PR updates the way inject behaves while attempting to inject non-compliant pods, i.e, pods that have issues related to host network, UDP port, sidecars and automountServiceAccountToken

Now instead of displaying warning messages and writing an uninjected YAML to stdout, inject throws an error. For example :

$ cat cli/cmd/testdata/inject_emojivoto_deployment_hostNetwork_true.input.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
  namespace: emojivoto
spec:
  replicas: 1
  selector:
    matchLabels:
      app: web-svc
  template:
    metadata:
      labels:
        app: web-svc
    spec:
      containers:
      - env:
        - name: WEB_PORT
          value: "80"
        - name: EMOJISVC_HOST
          value: emoji-svc.emojivoto:8080
        - name: VOTINGSVC_HOST
          value: voting-svc.emojivoto:8080
        - name: INDEX_BUNDLE
          value: dist/index_bundle.js
        image: buoyantio/emojivoto-web:v3
        name: web-svc
        ports:
        - containerPort: 9100
          hostPort: 9100
          name: http
      hostNetwork: true
---
$ cat cli/cmd/testdata/inject_emojivoto_deployment_hostNetwork_true.input.yml | bin/go-run cli inject -

Error transforming resources: failed to inject deployment/web - pods use host networking

@mayankshah1607
Copy link
Contributor Author

mayankshah1607 commented May 7, 2020

Similarly, when the input has multiple non-compliant pods or a mix of compliant and non-compliant, the errors are accumulated and displayed as a single message and nothing is injected

$ echo bad.yaml | bin/go-run cli inject -

Error transforming resources: failed to inject deployment/web - pods have a 3rd party proxy or initContainer already injected, 
failed to inject deployment/web - pods use host networking

Find bad.yaml here

@grampelberg grampelberg assigned alpeb and kleimkuhler and unassigned alpeb May 11, 2020
@mayankshah1607
Copy link
Contributor Author

Ping @kleimkuhler @alpeb

Copy link
Member

@alpeb alpeb left a comment

Choose a reason for hiding this comment

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

Looking good 👍

cli/cmd/inject.go Outdated Show resolved Hide resolved
cli/cmd/inject.go Outdated Show resolved Hide resolved
cli/cmd/inject_util.go Outdated Show resolved Hide resolved
@alpeb
Copy link
Member

alpeb commented Jun 1, 2020

Can you also please fix the referred issue number in the description?

@mayankshah1607 mayankshah1607 force-pushed the mayank/proxy-injector-error branch from fe71f52 to 5b20c62 Compare June 6, 2020 08:31
@mayankshah1607
Copy link
Contributor Author

mayankshah1607 commented Jun 6, 2020

@alpeb Thanks for the tip on wrapped errors - learnt something new! 😄
I've updated the code according to your comments. Had to force push as I ran into some problems while rebasing. But you might want to take a look at this commit in particular to see the new changes w.r.t to the comments on error accumulation mechanism. PTAL!
Thanks 😄

cli/cmd/inject.go Outdated Show resolved Hide resolved
@alpeb
Copy link
Member

alpeb commented Jun 11, 2020

@mayankshah1607 Thanks for having humored me with the error wrapping suggestion. After having become more comfortable with that concept I realize now it's really meant for adding context to errors and not really for accumulating errors. So I take back that suggestion.
I still think however that processYAML() and throwInjectErrors() should return an array of accumulated errors ([]error). LMKWYT.

@mayankshah1607 mayankshah1607 requested a review from a team as a code owner June 16, 2020 06:35
@alpeb
Copy link
Member

alpeb commented Jun 16, 2020

I think you should also reintroduce the logic to properly concatenate the error messages. Currently doing linkerd inject for example on a resources with both hostNetwork and automountServiceAccountToken yields something like this:

Error transforming resources: [failed to inject deployment/emoji - [automountServiceAccountToken set to "false" hostNetwork is enabled]]

@mayankshah1607 mayankshah1607 force-pushed the mayank/proxy-injector-error branch from f11fcc2 to 99726e3 Compare June 16, 2020 15:37
Copy link
Member

@alpeb alpeb left a comment

Choose a reason for hiding this comment

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

Almost there!

Comment on lines 538 to 546
func throwInjectError(report *inject.Report) []error {

errs := []error{}

const (
disabledAutomountServiceAccountToken = "disabled_automount_service_account_token_account"
hostNetworkEnabled = "host_network_enabled"
sidecarExists = "sidecar_already_exists"
udpPortsEnabled = "udp_ports_enabled"
Copy link
Member

Choose a reason for hiding this comment

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

Given this function is all about inject.Report, I think it's better to move it into report.go and make it a method of that struct. That will also avoid having to repeat these consts.

Copy link
Contributor Author

@mayankshah1607 mayankshah1607 Jun 19, 2020

Choose a reason for hiding this comment

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

@alpeb Done! You can find that refactor in this commit. (Had to rebase against master because some of the CI integration tests didn't seem to run)

Update injection process to throw an error when the reason for failure is due to sidecar, udp, automountServiceAccountToken or hostNetwork

Signed-off-by: Mayank Shah <mayankshah1614@gmail.com>
Signed-off-by: Mayank Shah <mayankshah1614@gmail.com>
Signed-off-by: Mayank Shah <mayankshah1614@gmail.com>
Signed-off-by: Mayank Shah <mayankshah1614@gmail.com>
Signed-off-by: Mayank Shah <mayankshah1614@gmail.com>
Signed-off-by: Mayank Shah <mayankshah1614@gmail.com>
Signed-off-by: Mayank Shah <mayankshah1614@gmail.com>
Signed-off-by: Mayank Shah <mayankshah1614@gmail.com>
Signed-off-by: Mayank Shah <mayankshah1614@gmail.com>
Signed-off-by: Mayank Shah <mayankshah1614@gmail.com>
- rename `shouldInjectThrowError` to `throwInjectError`
- `throwInjectError` accumulates all errors into a single error mesage
instead of short circuiting at the first occurence of an error
- update `processYAML` to accumulate error in a new error object rather
that a slice of string
- reuse errors messages from `inject.Reasons` map

Signed-off-by: Mayank Shah <mayankshah1614@gmail.com>
Signed-off-by: Mayank Shah <mayankshah1614@gmail.com>
Signed-off-by: Mayank Shah <mayankshah1614@gmail.com>
Signed-off-by: Mayank Shah <mayankshah1614@gmail.com>
Signed-off-by: Mayank Shah <mayankshah1614@gmail.com>
Signed-off-by: Mayank Shah <mayankshah1614@gmail.com>
Signed-off-by: Mayank Shah <mayankshah1614@gmail.com>
@mayankshah1607 mayankshah1607 force-pushed the mayank/proxy-injector-error branch from 99726e3 to 69ac7fc Compare June 19, 2020 06:00
Signed-off-by: Mayank Shah <mayankshah1614@gmail.com>
@mayankshah1607 mayankshah1607 requested a review from alpeb June 19, 2020 07:38
Copy link
Member

@alpeb alpeb left a comment

Choose a reason for hiding this comment

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

Thanks @mayankshah1607 !

@mayankshah1607
Copy link
Contributor Author

mayankshah1607 commented Jun 22, 2020

Pinging @zaharidichev for one more approval! 😄

Copy link
Contributor

@ihcsim ihcsim left a comment

Choose a reason for hiding this comment

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

LGTM. Just one minor feedback on the stdout output, and one question on the stderr output.

Also, it looks like we aren't handling the case when the automountServiceAccountToken property is defined in the service account YAML. E.g.,

kind: ServiceAccount
apiVersion: v1
metadata:
  name: emoji
  namespace: emojivoto
automountServiceAccountToken: false

@alpeb @grampelberg do we want an issue to track that?

cli/cmd/inject.go Outdated Show resolved Hide resolved
@@ -304,6 +310,12 @@ func (resourceTransformerInject) generateReport(reports []inject.Report, output
output.Write([]byte(fmt.Sprintf("%s %s\n", okStatus, udpDesc)))
}

if len(automountServiceAccountTokenFalse) > 0 {
output.Write([]byte(fmt.Sprintf("%s \"automountServiceAccountToken: false\" detected in %s\n", warnStatus, strings.Join(automountServiceAccountTokenFalse, ", "))))
Copy link
Contributor

Choose a reason for hiding this comment

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

For my own understanding, output writes to stderr, right? But I can't seem to get the CLI to output this error. What am I missing?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, I think this might be redundant. The CLI will error out before this part of the code is executed.

Copy link
Contributor

Choose a reason for hiding this comment

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

Let's remove it then. Thanks.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done 👍

@alpeb
Copy link
Member

alpeb commented Jun 22, 2020

Also, it looks like we aren't handling the case when the automountServiceAccountToken property is defined in the service account YAML. E.g.,

Ah I didn't think of that... I guess the best we can do is to stop ignoring ServiceAccount manifests during injection and issue a warning whenever we encounter automountServiceAccountToken: false. Not outright failing because the SA wouldn't necessary belong to a workload being injected.

Signed-off-by: Mayank Shah <mayankshah1614@gmail.com>
Signed-off-by: Mayank Shah <mayankshah1614@gmail.com>
@mayankshah1607
Copy link
Contributor Author

@alpeb @ihcsim Just to confirm my understanding - we should only error out automountServiceAccountToken: false when the object Kind is not a ServiceAccount, correct?

@ihcsim
Copy link
Contributor

ihcsim commented Jun 23, 2020

@mayankshah1607 That's correct. I created a separate issue (#4651) to deal with ServiceAccount kind.

Signed-off-by: Mayank Shah <mayankshah1614@gmail.com>
- Errors from each manifest to appear on new line

Signed-off-by: Mayank Shah <mayankshah1614@gmail.com>
Signed-off-by: Mayank Shah <mayankshah1614@gmail.com>
Signed-off-by: Mayank Shah <mayankshah1614@gmail.com>
Signed-off-by: Mayank Shah <mayankshah1614@gmail.com>
Signed-off-by: Mayank Shah <mayankshah1614@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

inject: throw an error while attempting to inject non-compliant pods
4 participants