Skip to content
This repository has been archived by the owner on Feb 24, 2020. It is now read-only.

stage1: move more logic out of AppUnit #3496

Merged
merged 1 commit into from
Jan 16, 2017
Merged

Conversation

squeed
Copy link
Contributor

@squeed squeed commented Dec 23, 2016

Try and simplify app unit generation in a few ways This is in preparation for pluggable stage2 isolation.

  • generate an intermediate struct with runtime information, rather than generating unit directives directly
  • Split systemd-specific and more generic unit code

@squeed
Copy link
Contributor Author

squeed commented Jan 3, 2017

Failures are known flake (TestAppUserGroup)

@lucab lucab added this to the v1.23.0 milestone Jan 5, 2017
@lucab lucab self-requested a review January 5, 2017 11:00
}

// getAppResources processes any isolators that manipulate cgroups.
func getAppResources(isolators types.Isolators) (appResources, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

computeAppResources

}

if !ok {
fmt.Fprintf(os.Stderr, "warning: resource/%s isolator set but support disabled in the kernel, skipping\n", name)
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 return a named or typed Error and do the warn printing in the stage1 entrypoint code, not here in common.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hmm. This is tricky because this could possibly be the case for multiple isolators. What's the idiomatic way of representing multiple warnings?

Copy link
Contributor

Choose a reason for hiding this comment

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

// ErrIsolatorUnsupported is the error that determines whether the specified isolator is supported in the kernel.
type ErrIsolatorUnsupported struct {
  Isolator string
}

func (e ErrIsolatorUnsupported) Error() string {
  return "unsupported isolator "+e.Isolator
}

The consumer would then do a type assertion if it is interested which isolator is unsupported:

  if unsupportedErr, ok := err.(ErrIsolatorUnsupported); ok {
    fmt.Println(unsupportedErr.Isolator)
  }

const (
ModeBlacklist filterType = iota
ModeWhitelist filterType = iota
)
Copy link
Contributor

Choose a reason for hiding this comment

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

nit:

const (
	ModeBlacklist filterType = iota
	ModeWhitelist
)

filterPrefix := sdBlacklistPrefix
if sf.mode == ModeWhitelist {
filterPrefix = sdWhitelistPrefix
}
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: let's make a switch statement here and err out on unknown mode.

@@ -284,134 +283,121 @@ func (uw *UnitWriter) Error() error {
}

func (uw *UnitWriter) AppUnit(ra *schema.RuntimeApp, binPath string, opts ...*unit.UnitOption) {
if uw.err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

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

if uw.err != nil { was removed here, can you elaborate why?

uw.err = errwrap.Wrap(errors.New("unable to write environment file for systemd"), err)
opts = uw.AppSystemdUnit(pa, binPath, opts)

if uw.err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

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

The if uw.err != nil check must be at the beginning of the function to exit immediately and not execute any code in case a previous err happened.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not in this case - AppSystemdUnit can also apply err, in which case we should exit.

I'm not sure why this is structured this way, but it was like this when I got here.

Copy link
Contributor

Choose a reason for hiding this comment

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

This was structured the "errWriter" way, see https://blog.golang.org/errors-are-values, applied to the unitWriter.

The reasoning is that the caller can call unitWriter methods sequentially and check the error only once at the end of the sequence to avoid long if err != nil ... repetitions to the unit writer.

If we don't put the if uw.err != nil check at the top of the function, we break this semantic. I should and will add a reference to the godoc to the above mentioned article.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I see what you mean - though there is only one caller in this case. ::shrugs::

}

// AppSystemdUnit sets up an application for isolation via systemd
func (uw *UnitWriter) AppSystemdUnit(pa *preparedApp, binPath string, opts []*unit.UnitOption) []*unit.UnitOption {
Copy link
Contributor

Choose a reason for hiding this comment

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

This function should check if any previous error occured using if uw.err != nil { return nil } and not execute any code.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That is not needed. There is nothing that could set err before this function.

Copy link
Contributor

@s-urbaniak s-urbaniak Jan 10, 2017

Choose a reason for hiding this comment

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

A previous UnitWriter method invocation could cause to set the err before this function, hence it is needed. You don't know if the UnitWriter is not in errornous state already.

@squeed
Copy link
Contributor Author

squeed commented Jan 10, 2017

@s-urbaniak updated, thanks!

Copy link
Contributor

@s-urbaniak s-urbaniak left a comment

Choose a reason for hiding this comment

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

just a small nit, but LGTM otherwise, thanks!

}

if !ok {
fmt.Fprintf(os.Stderr, "warning: resource/%s isolator set but support disabled in the kernel, skipping\n", name)
Copy link
Contributor

Choose a reason for hiding this comment

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

ok, this is still here, and it was there also in the old code. I'll submit an issue to get rid of all fmt.Fprintf occurrences and replace them with respective injectable warnf loggers.

@lucab
Copy link
Member

lucab commented Jan 13, 2017

This got a conflict in the meanwhile. It looks fine in general, I'll do a last pass after the rebase.

@jonboulle
Copy link
Contributor

@squeed bump

@squeed
Copy link
Contributor Author

squeed commented Jan 13, 2017

Rebased, thanks!

Copy link
Member

@lucab lucab left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Contributor

@s-urbaniak s-urbaniak left a comment

Choose a reason for hiding this comment

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

LGTM (there is just some rebase conflict to be resolved)

@lucab
Copy link
Member

lucab commented Jan 16, 2017

This PR got hit by a github downtime, so it is in a kind for weird state. @squeed Mind rebasing and pushing again?

@squeed
Copy link
Contributor Author

squeed commented Jan 16, 2017

Rebased - let's go for green!

@jonboulle
Copy link
Contributor

fail :-(

@squeed
Copy link
Contributor Author

squeed commented Jan 16, 2017

Neat, it printed the byte sequence. The error message is

add: pod "b5b86b03-4e7f-4251-bc60-aed97540ef63" isn't currently running

I'll dig in to this.

Try and simplify app unit generation in a few ways. This is in
preparation for pluggable stage2 isolation engines.

- generate a struct with runtime information, rather than generating
    unit directives directly from isolators, etc.
- Split systemd-specific and more generic unit code
@squeed
Copy link
Contributor Author

squeed commented Jan 16, 2017

Bad merge - OnFailure snuck back in. Fixed.

@s-urbaniak s-urbaniak merged commit 6041ab6 into rkt:master Jan 16, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants