Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions components/common/src/templating.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,10 @@ lazy_static! {
/// A convenience method that compiles a package's install and uninstall hooks and any configuration
/// templates in its config_install folder
pub async fn compile_for_package_install(package: &PackageInstall,
feature_flags: FeatureFlag)
feature_flags: FeatureFlag,
token: Option<&str>)
-> Result<()> {
let pkg = package::Pkg::from_install(package).await?;
let pkg = package::Pkg::from_install(package, token).await?;
Comment thread
mwrock marked this conversation as resolved.

fs::SvcDir::new(&pkg.name, &pkg.svc_user, &pkg.svc_group).create()?;

Expand Down Expand Up @@ -464,7 +465,7 @@ mod tests {
create_with_content(config_path.join("config.txt"),
"config message is {{cfg.message}}");

compile_for_package_install(&pkg_install, FeatureFlag::empty()).await
compile_for_package_install(&pkg_install, FeatureFlag::empty(), None).await
.expect("compile package");

assert_eq!(
Expand Down
2 changes: 1 addition & 1 deletion components/common/src/templating/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1046,7 +1046,7 @@ mod tests {
let output_dir = root.join("output");
fs::create_dir_all(&output_dir).expect("create output dir");

let pkg = Pkg::from_install(&pkg_install).await.unwrap();
let pkg = Pkg::from_install(&pkg_install, None).await.unwrap();
let cfg = Cfg::new(&pkg, None).unwrap();
let ctx = RenderContext::new(&pkg, &cfg);

Expand Down
11 changes: 5 additions & 6 deletions components/common/src/templating/hooks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,12 +288,11 @@ pub trait PackageMaintenanceHookExt: Hook<ExitValue = ExitStatus> + Sync {
let hook_name = Self::FILE_NAME;
ui.status(Status::Executing,
format!("{} hook for '{}'", hook_name, package.ident()))?;
templating::compile_for_package_install(package, feature_flags).await?;
templating::compile_for_package_install(package, feature_flags, token).await?;

// Only windows uses svc_password
#[cfg(target_os = "windows")]
let pkg = {
let mut pkg = Pkg::from_install(package).await?;
let mut pkg = Pkg::from_install(package, token).await?;
// Hooks do not have access to svc_passwords so we execute them under the
// current user account.
if let Some(user) = habitat_core::os::users::get_current_username()? {
Expand All @@ -309,7 +308,7 @@ pub trait PackageMaintenanceHookExt: Hook<ExitValue = ExitStatus> + Sync {
};
#[cfg(not(target_os = "windows"))]
let pkg = {
let mut pkg = Pkg::from_install(package).await?;
let mut pkg = Pkg::from_install(package, token).await?;
// Pass through auth token if provided
if let Some(token_value) = token {
pkg.env
Expand Down Expand Up @@ -866,8 +865,8 @@ echo "The message is Hola Mundo"
.join(MetaFile::PackageType.to_string()),
"native");
}
let pkg = Pkg::from_install(&pkg_install).await
.expect("Could not create package!");
let pkg = Pkg::from_install(&pkg_install, None).await
.expect("Could not create package!");

// This is gross, but it actually works
let cfg_path = concrete_path.as_ref().join("default.toml");
Expand Down
15 changes: 9 additions & 6 deletions components/common/src/templating/package.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ impl Env {
///
/// This means we work on any operating system, as long as you can invoke the Supervisor,
/// without having to worry much about context.
pub async fn new(package: &PackageInstall) -> Result<Self> {
pub async fn new(package: &PackageInstall, token: Option<&str>) -> Result<Self> {
let mut env = package.environment_for_command()?;
let path = Self::transform_path(env.get(PATH_KEY), package.package_type()?).await?;
let path = Self::transform_path(env.get(PATH_KEY), package.package_type()?, token).await?;
env.insert(PATH_KEY.to_string(), path);
Ok(Env(env))
}
Expand All @@ -60,13 +60,16 @@ impl Env {
self.0.insert(key, value);
}

async fn transform_path(path: Option<&String>, package_type: PackageType) -> Result<String> {
async fn transform_path(path: Option<&String>,
package_type: PackageType,
token: Option<&str>)
-> Result<String> {
let mut paths: Vec<PathBuf> = match path {
Some(path) => env::split_paths(&path).collect(),
None => vec![],
};
match package_type {
PackageType::Standard => path::append_interpreter_and_env_path(&mut paths).await,
PackageType::Standard => path::append_interpreter_and_env_path(&mut paths, token).await,
PackageType::Native => path::append_env_path(&mut paths),
}
}
Expand Down Expand Up @@ -101,7 +104,7 @@ pub struct Pkg {
}

impl Pkg {
pub async fn from_install(package: &PackageInstall) -> Result<Self> {
pub async fn from_install(package: &PackageInstall, token: Option<&str>) -> Result<Self> {
let ident = FullyQualifiedPackageIdent::try_from(&package.ident)?;
let (svc_user, svc_group) = get_user_and_group(package)?;
let pkg = Pkg { svc_path: fs::svc_path(&package.ident.name),
Expand All @@ -116,7 +119,7 @@ impl Pkg {
svc_pid_file: fs::svc_pid_file(&package.ident.name),
svc_user,
svc_group,
env: Env::new(package).await?,
env: Env::new(package, token).await?,
deps: package.tdeps()?,
exposes: package.exposes()?,
exports: package.exports()?,
Expand Down
17 changes: 13 additions & 4 deletions components/common/src/util/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ const VERSION: &str = include_str!(concat!(env!("OUT_DIR"), "/VERSION"));
/// * If a known-working package identifier string cannot be parsed
/// * If the Supervisor is not executing inside a package, and if no interpreter package is
/// installed
async fn interpreter_paths() -> Result<Vec<PathBuf>> {
async fn interpreter_paths(token: Option<&str>) -> Result<Vec<PathBuf>> {
// First, we'll check if we're running inside a package. If we are, then we should be able to
// access the `../DEPS` metadata file and read it to get the specific version of the
// interpreter.
Expand Down Expand Up @@ -95,6 +95,13 @@ async fn interpreter_paths() -> Result<Vec<PathBuf>> {
// Nope, no packages of the interpreter installed. Now we're going to see if the
// interpreter command is present on `PATH`.
Err(_) => {
// Prefer the explicitly-passed token; fall back to the environment variable.
let env_token = if token.is_none() {
env::var(habitat_core::AUTH_TOKEN_ENVVAR).ok()
} else {
None
};
let auth_token = token.or(env_token.as_deref());
match install::type_erased_start(&mut ui::NullUi::new(),
&default_bldr_url(),
&ChannelIdent::default(),
Expand All @@ -105,7 +112,7 @@ async fn interpreter_paths() -> Result<Vec<PathBuf>> {
VERSION,
FS_ROOT_PATH.as_path(),
&cache_artifact_path(None::<String>),
env::var("HAB_AUTH_TOKEN").ok().as_deref(),
auth_token,
&InstallMode::default(),
&LocalPackageUsage::default(),
InstallHookMode::default()).await
Expand All @@ -129,8 +136,10 @@ fn root_paths(paths: &mut [PathBuf]) {
}

/// Append the the interpreter path and environment PATH variable to the provided path entries
pub async fn append_interpreter_and_env_path(path_entries: &mut Vec<PathBuf>) -> Result<String> {
let mut paths = interpreter_paths().await?;
pub async fn append_interpreter_and_env_path(path_entries: &mut Vec<PathBuf>,
token: Option<&str>)
-> Result<String> {
let mut paths = interpreter_paths(token).await?;
Comment thread
mwrock marked this conversation as resolved.
root_paths(&mut paths);
path_entries.append(&mut paths);
append_env_path(path_entries)
Expand Down
2 changes: 1 addition & 1 deletion components/sup/src/command/shell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ pub async fn sh() -> Result<()> {

async fn set_path() -> Result<()> {
let mut paths: Vec<PathBuf> = Vec::new();
let new_path = path::append_interpreter_and_env_path(&mut paths).await?;
let new_path = path::append_interpreter_and_env_path(&mut paths, None).await?;

debug!("Setting the PATH to {}", &new_path);
// TODO: Audit that the environment access only happens in single-threaded code.
Expand Down
4 changes: 2 additions & 2 deletions components/sup/src/manager/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -605,7 +605,7 @@ impl Service {
// the current user.
#[cfg(windows)]
async fn resolve_pkg(package: &PackageInstall, spec: &ServiceSpec) -> Result<Pkg> {
let mut pkg = Pkg::from_install(package).await?;
let mut pkg = Pkg::from_install(package, None).await?;
if spec.svc_encrypted_password.is_none()
&& pkg.svc_user == DEFAULT_USER
&& let Some(user) = users::get_current_username()?
Expand All @@ -617,7 +617,7 @@ impl Service {

#[cfg(unix)]
async fn resolve_pkg(package: &PackageInstall, _spec: &ServiceSpec) -> Result<Pkg> {
Ok(Pkg::from_install(package).await?)
Ok(Pkg::from_install(package, None).await?)
}

/// Returns the config root given the package and optional config-from path.
Expand Down
2 changes: 1 addition & 1 deletion components/sup/src/manager/service/hooks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -751,7 +751,7 @@ mod tests {
.join(MetaFile::PackageType.to_string()),
"native");
}
Pkg::from_install(&pkg_install).await.unwrap()
Pkg::from_install(&pkg_install, None).await.unwrap()
}

fn ctx<'a>(service_group: &'a ServiceGroup,
Expand Down
2 changes: 1 addition & 1 deletion components/sup/src/manager/service/pipe_hook_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ mod tests {
PathBuf::from("/tmp"),
PathBuf::from("/tmp"),
PathBuf::from("/tmp"));
Pkg::from_install(&pkg_install).await.unwrap()
Pkg::from_install(&pkg_install, None).await.unwrap()
}

#[tokio::test]
Expand Down
17 changes: 17 additions & 0 deletions test/end-to-end/test_pkg_install.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,23 @@ Describe "pkg install" {
}
}

if ($IsLinux) {
It "installs interpreter from builder for install hooks using --auth token" {
Remove-Item /hab/pkgs/core/busybox-static -Recurse -Force -ErrorAction Ignore
Remove-Item "/hab/cache/artifacts/core-busybox-static-*" -ErrorAction Ignore
$token = $env:HAB_AUTH_TOKEN
try {
$env:HAB_AUTH_TOKEN = $null
$cached = Get-Item "/hab/cache/artifacts/$env:HAB_ORIGIN-dep-pkg-1*"
Write-Host (hab pkg install $cached.FullName --auth "$token" | Out-String)
} finally {
$env:HAB_AUTH_TOKEN = $token
}
$LASTEXITCODE | Should -Be 0
Get-Content "$(hab pkg path $env:HAB_ORIGIN/dep-pkg-1)/INSTALL_HOOK_STATUS" | Should -Be "0"
}
}

It "installs all dependencies and executes all install hooks" {
$cached = Get-Item "/hab/cache/artifacts/$env:HAB_ORIGIN-dep-pkg-3*"
hab pkg install $cached.FullName
Expand Down
Loading