Skip to content
This repository has been archived by the owner on Apr 18, 2019. It is now read-only.

moving some common functionality from habitat #90

Merged
merged 1 commit into from
Jan 18, 2019
Merged

moving some common functionality from habitat #90

merged 1 commit into from
Jan 18, 2019

Conversation

mwrock
Copy link
Contributor

@mwrock mwrock commented Nov 17, 2018

This PR accompanies habitat-sh/habitat#5866 which moves most of the hook and templating code from the supervisor into the common crate of the habitat repo. There was some functionality that also needed to be used commonly but seemed better suited here:

sup/src/fs.rs -> folded into /core/src/fs.rs
sup/src/sys/abilities -> folded into /core/src/os/users
sup/src/sys/user -> folded into /core/src/os/users
sup/src/manager/service/dir.rs -> folded into /core/src/fs.rs

Signed-off-by: mwrock matt@mattwrock.com

@thesentinels
Copy link
Contributor

Thanks for the pull request! Here is what will happen next:

  1. Your PR will be reviewed by the maintainers
  2. If everything looks good, one of them will approve it, and your PR will be merged.

Thank you for contributing!

@mwrock
Copy link
Contributor Author

mwrock commented Nov 26, 2018

related: habitat-sh/habitat#5161

@baumanj
Copy link
Contributor

baumanj commented Nov 27, 2018

Starting to review this now

@@ -168,11 +179,17 @@ pub enum Error {
WrongActivePackageTarget(package::PackageTarget, package::PackageTarget),
}

unsafe impl Send for Error {}
unsafe impl Sync for Error {}
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm curious why these are necessary/appropriate. According to the docs, Send and Sync are "automatically implemented when the compiler determines it's appropriate".

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It was the only way I could get of a compile error compiling the supervisor against this. Something releted to not implementing send. I don't remember it well. I'll dig it up.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

heh...go figure...I can't repro that error now. I have a hunch that is due to some changes I made yesterday in the supervisor.

Copy link
Contributor

Choose a reason for hiding this comment

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

The issue here is the addition of handlebars::error::RenderError to the core Error enum. The version we're at fails to require Sync in one of its fields. See sunng87/handlebars-rust#194.

Copy link
Contributor

@baumanj baumanj 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 couple small things. Overall, I'm really happy to see this made more modular.

config_from
.and_then(|p| Some(p.as_path()))
.unwrap_or(&package.installed_path)
.join("hooks"),
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this can be simplified to:

            config_from.unwrap_or(&package.installed_path).join("hooks"),

Copy link
Contributor

Choose a reason for hiding this comment

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

Also, the only caller I see for this function passes None for config_from, so it seems like we could eliminate that argument entirely and just pass

            package.installed_path.join("hooks"),

to Self::load. If that argument is needed, I'd rather eliminate the Option and make the callers do:

from_package_install(package, &package.installed_path)
// vs
from_package_install(package, &some_other_path)

Since I think that's more evocative to read at the call-site than

from_package_install(package, None)
// vs
from_package_install(package, &some_other_path)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The config_from is explicitly passed by the supervisor. You just don't see it since that is in a separate repo.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, I see here and here.

I think I get it now. This is an Option because ServiceSpec's field is an option. That makes more sense.

I think we may be better served by removing the optionality from ServiceSpec; I'm not convinced it's necessary. But that's a change for another day.

@@ -10,11 +10,13 @@ base64 = "*"
gcc = "0.3"

[dependencies]
actix-web = { version = "*", default-features = false }
Copy link
Contributor

Choose a reason for hiding this comment

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

Why do we need Actix in core now?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

HealthCheck uses its StatusCode but based on your point below, we probably don't need that here after all.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Its used by HealthCheck. I looked at moving that back to the supervisor as you suggested below but its pretty well coupled with the hooks (see my comment below).

@@ -37,6 +37,7 @@ pub enum Error {
/// Occurs when a `habitat_core::package::PackageArchive` is being read.
ArchiveError(libarchive::error::ArchiveError),
BadBindingMode(String),
BadEnvConfig(String),
Copy link
Contributor

Choose a reason for hiding this comment

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

It'd be nice to have a doc comment on this, similar to the others.

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 sure why github is not showing this as "outdated" its been fixed

PermissionFailed(String),
/// Error parsing the contents of a plan file were incomplete or malformed.
PlanMalformed,
// When CreateProcessAsUserW does not have the correct privileges
PrivilegeNotHeld,
/// When an error occurs parsing or compiling a regular expression.
RegexParse(regex::Error),
/// Whwn an error occurs serializing rendering context
Copy link
Contributor

Choose a reason for hiding this comment

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

"Whwn" -> "When"

use actix_web::http::StatusCode;

#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize)]
pub enum HealthCheck {
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this really need to be over here? What would anything outside the Supervisor need this for?

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. Keeping this in the supervisor actually looks a bit messy. It is referenced several times in the HealthCheckHook. Given how the HookTable works, all hooks need to be defined in core.

let cfg_renderer = config::CfgRenderer::new(pkg.path.join("config"))?;
cfg_renderer.compile(&pkg.name, &pkg, &ctx)?;

hooks::HookTable::from_package_install(package).compile(&pkg.name, &ctx);
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 you try to compile a hook that depends on things that aren't present in this limited rendering context (like census information)?

Seems like we should throw an error.

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'm assuming this comment is also targetted to config templates also? Currently it just renders nothing if there is nothing in the context. Thinking of the following example scenario, I'd prefer to raise a warning instead of an error:

There may be multiple config templates and some have, for example, binds and others do not. When the install hook fires at install time, it will need to compile all templates since it cannot assume which templates it will use. We wouldn't want the templates with the binds to error during installation.

Also for debug purposes, one might use hab pkg compile and there would be no bind context. So a warning informing the cli user that there is missing context would be nice but they could still render the templates.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

One extra point. I'm not certain yet how much we can control for that via the serde API.

Copy link
Contributor

Choose a reason for hiding this comment

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

I also thought we were going to have a specific install hook, or am I misremembering?

That might end up being cleaner, since we wouldn't necessarily need to bring over all the hooks, just the handlebars and context stuff.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah there is an InstallHook added to hooks.rs. Maybe it makes better sense for the HookTable not to include that hook and then just keep HookTable and the non-install hook implementations with the supervisor.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The downside of keeping the non-install hooks with the supervisor is that the hab pkg compile cli command will not be able to compile them. Also, future work is going to need to be able to compile the health-check via the cli.

@@ -0,0 +1,106 @@
// Copyright (c) 2017 Chef Software Inc. and/or applicable contributors
Copy link
Contributor

Choose a reason for hiding this comment

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

These also got moved to https://github.com/habitat-sh/habitat/blob/master/components/sup/src/test_helpers.rs... if we're moving them over here, the other tests in the supervisor that use them should pull them from here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ends up that the only files using these functions were moved over

Copy link
Contributor

@baumanj baumanj left a comment

Choose a reason for hiding this comment

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

The Sync issue on the Error enum will break habitat, so we can't merge this until we come up with a solution to that.

@mwrock
Copy link
Contributor Author

mwrock commented Nov 29, 2018

@christophermaier @baumanj Still not great but what do you think of f320dff for dealing with the RenderError issues?

@baumanj
Copy link
Contributor

baumanj commented Nov 29, 2018

@christophermaier @baumanj Still not great but what do you think of f320dff for dealing with the RenderError issues?

I think that's good! It's clean and small and I don't think should negatively impact the utility of the error messages at all. We might want to add a note to change it back when we upgrade the handlebars crate (maybe an issue, linked from our comments at the pinning in Cargo.toml), but otherwise I'm happy with it.

@mwrock
Copy link
Contributor Author

mwrock commented Dec 10, 2018

Note that this now keeps the supervisor specific hooks along with HookTable with the supervisor code. Only the Hook trait, supporting structs and the InstallHook remains here.

Also it is now possible to specify the directory where config files should be rendered to. They used to always render to svc_config_path. Configuration files to be referenced in an install hook will reside in a config_install directory and render to svc_config_install_path.

Copy link
Contributor

@christophermaier christophermaier left a comment

Choose a reason for hiding this comment

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

Looks good... I had a few suggestions around OS-specific code, which could very well be left for another PR.

For good record-keeping, though, this PR's title and body should be rewritten to reflect what's now going on (there isn't really any templating-specific code in here anymore, for instance).

#[cfg(target_os = "macos")]
pub fn can_run_services_as_svc_user() -> bool {
true
}
Copy link
Contributor

Choose a reason for hiding this comment

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

We should move this out of this module, since it doesn't pertain to Linux.

I'm not sure we really even need this implementation; I don't think any macOS code would make it down to anyplace that this function would be needed.

In the same spirit, if we're only pulling this module in on Linux, then all the #[cfg(target_os = "linux")] annotations end up being noise.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yup. I just double checked and don't see any scenario where code would reach here on a mac until it runs a supervisor and we support darwin package installs.

env::remove_var("USERNAME");
assert_eq!(get_current_username(), None)
assert_eq!(get_current_username(), None);
env::set_var("USERNAME", orig_user);
Copy link
Contributor

Choose a reason for hiding this comment

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

Any chance these two tests end up stepping on each other? They're both manipulating global state.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

TIL: cargo check runs tests in parallel. So yes.

I'd prefer to tackle this separately by refactoring the windows implementation of get_current_username to call the GetUserNameW API rather than checking the environment variable. Will file an issue.

Copy link
Contributor

Choose a reason for hiding this comment

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

Using an API call is probably a better way forward. And yeah, it sounds worth a separate PR 👍

If you do end up sticking with the environment variable approach, though, you'll want to look at using our new-ish locked env var tooling (which would also mean pulling it over here to the core crate).

@mwrock mwrock changed the title extract supervisor templating into core moving some common functionality from habitat Jan 14, 2019
Signed-off-by: mwrock <matt@mattwrock.com>
@mwrock mwrock merged commit 534e730 into master Jan 18, 2019
@mwrock mwrock deleted the templating branch January 18, 2019 20:50
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