forked from github-starred/komodo
clean up ecr
This commit is contained in:
15
Cargo.lock
generated
15
Cargo.lock
generated
@@ -518,17 +518,6 @@ dependencies = [
|
|||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "aws_ecr"
|
|
||||||
version = "1.9.0"
|
|
||||||
dependencies = [
|
|
||||||
"anyhow",
|
|
||||||
"aws-config",
|
|
||||||
"aws-sdk-ecr",
|
|
||||||
"run_command",
|
|
||||||
"tracing",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "axum"
|
name = "axum"
|
||||||
version = "0.6.20"
|
version = "0.6.20"
|
||||||
@@ -2266,7 +2255,7 @@ dependencies = [
|
|||||||
"async_timing_util",
|
"async_timing_util",
|
||||||
"aws-config",
|
"aws-config",
|
||||||
"aws-sdk-ec2",
|
"aws-sdk-ec2",
|
||||||
"aws_ecr",
|
"aws-sdk-ecr",
|
||||||
"axum 0.7.5",
|
"axum 0.7.5",
|
||||||
"axum-extra",
|
"axum-extra",
|
||||||
"base64 0.22.1",
|
"base64 0.22.1",
|
||||||
@@ -2292,6 +2281,7 @@ dependencies = [
|
|||||||
"rand",
|
"rand",
|
||||||
"reqwest 0.12.4",
|
"reqwest 0.12.4",
|
||||||
"resolver_api",
|
"resolver_api",
|
||||||
|
"run_command",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"serror",
|
"serror",
|
||||||
@@ -2317,7 +2307,6 @@ version = "1.9.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async_timing_util",
|
"async_timing_util",
|
||||||
"aws_ecr",
|
|
||||||
"axum 0.7.5",
|
"axum 0.7.5",
|
||||||
"axum-extra",
|
"axum-extra",
|
||||||
"bollard",
|
"bollard",
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ monitor_client = "1.8.0"
|
|||||||
periphery_client = { path = "client/periphery/rs" }
|
periphery_client = { path = "client/periphery/rs" }
|
||||||
formatting = { path = "lib/formatting" }
|
formatting = { path = "lib/formatting" }
|
||||||
command = { path = "lib/command" }
|
command = { path = "lib/command" }
|
||||||
aws_ecr = { path = "lib/aws_ecr" }
|
|
||||||
logger = { path = "lib/logger" }
|
logger = { path = "lib/logger" }
|
||||||
git = { path = "lib/git" }
|
git = { path = "lib/git" }
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ path = "src/main.rs"
|
|||||||
monitor_client = { workspace = true, features = ["mongo"] }
|
monitor_client = { workspace = true, features = ["mongo"] }
|
||||||
periphery_client.workspace = true
|
periphery_client.workspace = true
|
||||||
formatting.workspace = true
|
formatting.workspace = true
|
||||||
aws_ecr.workspace = true
|
|
||||||
logger.workspace = true
|
logger.workspace = true
|
||||||
git.workspace = true
|
git.workspace = true
|
||||||
# mogh
|
# mogh
|
||||||
@@ -30,6 +29,7 @@ derive_variants.workspace = true
|
|||||||
mongo_indexed.workspace = true
|
mongo_indexed.workspace = true
|
||||||
resolver_api.workspace = true
|
resolver_api.workspace = true
|
||||||
toml_pretty.workspace = true
|
toml_pretty.workspace = true
|
||||||
|
run_command.workspace = true
|
||||||
parse_csl.workspace = true
|
parse_csl.workspace = true
|
||||||
mungos.workspace = true
|
mungos.workspace = true
|
||||||
slack.workspace = true
|
slack.workspace = true
|
||||||
@@ -38,6 +38,7 @@ svi.workspace = true
|
|||||||
ordered_hash_map.workspace = true
|
ordered_hash_map.workspace = true
|
||||||
urlencoding.workspace = true
|
urlencoding.workspace = true
|
||||||
aws-sdk-ec2.workspace = true
|
aws-sdk-ec2.workspace = true
|
||||||
|
aws-sdk-ecr.workspace = true
|
||||||
aws-config.workspace = true
|
aws-config.workspace = true
|
||||||
tokio-util.workspace = true
|
tokio-util.workspace = true
|
||||||
axum-extra.workspace = true
|
axum-extra.workspace = true
|
||||||
|
|||||||
@@ -12,12 +12,13 @@ use monitor_client::{
|
|||||||
all_logs_success,
|
all_logs_success,
|
||||||
build::{Build, CloudRegistryConfig, ImageRegistry},
|
build::{Build, CloudRegistryConfig, ImageRegistry},
|
||||||
builder::{AwsBuilderConfig, Builder, BuilderConfig},
|
builder::{AwsBuilderConfig, Builder, BuilderConfig},
|
||||||
config::core::AwsEcrConfig,
|
config::core::{AwsEcrConfig, AwsEcrConfigWithCredentials},
|
||||||
deployment::DeploymentState,
|
deployment::DeploymentState,
|
||||||
monitor_timestamp,
|
monitor_timestamp,
|
||||||
permission::PermissionLevel,
|
permission::PermissionLevel,
|
||||||
server::{stats::SeverityLevel, Server},
|
server::{stats::SeverityLevel, Server},
|
||||||
server_template::aws::AwsServerTemplateConfig,
|
server_template::aws::AwsServerTemplateConfig,
|
||||||
|
to_monitor_name,
|
||||||
update::{Log, Update},
|
update::{Log, Update},
|
||||||
user::{auto_redeploy_user, User},
|
user::{auto_redeploy_user, User},
|
||||||
},
|
},
|
||||||
@@ -39,9 +40,12 @@ use tokio_util::sync::CancellationToken;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
cloud::{
|
cloud::{
|
||||||
aws::ec2::{
|
aws::{
|
||||||
launch_ec2_instance, terminate_ec2_instance_with_retry,
|
ec2::{
|
||||||
Ec2Instance,
|
launch_ec2_instance, terminate_ec2_instance_with_retry,
|
||||||
|
Ec2Instance,
|
||||||
|
},
|
||||||
|
ecr,
|
||||||
},
|
},
|
||||||
BuildCleanupData,
|
BuildCleanupData,
|
||||||
},
|
},
|
||||||
@@ -762,23 +766,32 @@ async fn validate_account_extract_registry_token_aws_ecr(
|
|||||||
ImageRegistry::AwsEcr(label) => {
|
ImageRegistry::AwsEcr(label) => {
|
||||||
let config = core_config().aws_ecr_registries.get(label);
|
let config = core_config().aws_ecr_registries.get(label);
|
||||||
let token = match config {
|
let token = match config {
|
||||||
Some(AwsEcrConfig {
|
Some(AwsEcrConfigWithCredentials {
|
||||||
region,
|
region,
|
||||||
access_key_id,
|
access_key_id,
|
||||||
secret_access_key,
|
secret_access_key,
|
||||||
..
|
..
|
||||||
}) => Some(
|
}) => {
|
||||||
aws_ecr::get_ecr_token(
|
ecr::maybe_create_repo(
|
||||||
region,
|
&to_monitor_name(&build.name),
|
||||||
|
region.to_string(),
|
||||||
access_key_id,
|
access_key_id,
|
||||||
secret_access_key,
|
secret_access_key,
|
||||||
)
|
)
|
||||||
.await
|
.await?;
|
||||||
.context("failed to get aws ecr token")?,
|
Some(
|
||||||
),
|
ecr::get_ecr_token(
|
||||||
|
region,
|
||||||
|
access_key_id,
|
||||||
|
secret_access_key,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.context("failed to get aws ecr token")?,
|
||||||
|
)
|
||||||
|
}
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
Ok((token, config.cloned()))
|
Ok((token, config.map(AwsEcrConfig::from)))
|
||||||
}
|
}
|
||||||
ImageRegistry::Custom(_) => {
|
ImageRegistry::Custom(_) => {
|
||||||
Err(anyhow!("Custom image registry is not implemented"))
|
Err(anyhow!("Custom image registry is not implemented"))
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ use monitor_client::{
|
|||||||
api::execute::*,
|
api::execute::*,
|
||||||
entities::{
|
entities::{
|
||||||
build::{Build, ImageRegistry},
|
build::{Build, ImageRegistry},
|
||||||
|
config::core::AwsEcrConfig,
|
||||||
deployment::{Deployment, DeploymentImage},
|
deployment::{Deployment, DeploymentImage},
|
||||||
get_image_name,
|
get_image_name,
|
||||||
permission::PermissionLevel,
|
permission::PermissionLevel,
|
||||||
@@ -84,7 +85,10 @@ impl Resolve<Deploy, (User, Update)> for State {
|
|||||||
DeploymentImage::Build { build_id, version } => {
|
DeploymentImage::Build { build_id, version } => {
|
||||||
let build = resource::get::<Build>(&build_id).await?;
|
let build = resource::get::<Build>(&build_id).await?;
|
||||||
let image_name = get_image_name(&build, |label| {
|
let image_name = get_image_name(&build, |label| {
|
||||||
core_config().aws_ecr_registries.get(label)
|
core_config()
|
||||||
|
.aws_ecr_registries
|
||||||
|
.get(label)
|
||||||
|
.map(AwsEcrConfig::from)
|
||||||
})
|
})
|
||||||
.context("failed to create image name")?;
|
.context("failed to create image name")?;
|
||||||
let version = if version.is_none() {
|
let version = if version.is_none() {
|
||||||
@@ -177,9 +181,13 @@ impl Resolve<Deploy, (User, Update)> for State {
|
|||||||
core_config.github_accounts.get(¶ms.account).cloned(),
|
core_config.github_accounts.get(¶ms.account).cloned(),
|
||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
ImageRegistry::AwsEcr(label) => {
|
ImageRegistry::AwsEcr(label) => (
|
||||||
(None, core_config.aws_ecr_registries.get(label).cloned())
|
None,
|
||||||
}
|
core_config
|
||||||
|
.aws_ecr_registries
|
||||||
|
.get(label)
|
||||||
|
.map(AwsEcrConfig::from),
|
||||||
|
),
|
||||||
ImageRegistry::Custom(_) => {
|
ImageRegistry::Custom(_) => {
|
||||||
return Err(anyhow!("Custom ImageRegistry not yet supported"))
|
return Err(anyhow!("Custom ImageRegistry not yet supported"))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use aws_sdk_ecr::Client as EcrClient;
|
|||||||
use run_command::async_run_command;
|
use run_command::async_run_command;
|
||||||
|
|
||||||
#[tracing::instrument(skip(access_key_id, secret_access_key))]
|
#[tracing::instrument(skip(access_key_id, secret_access_key))]
|
||||||
pub async fn make_ecr_client(
|
async fn make_ecr_client(
|
||||||
region: String,
|
region: String,
|
||||||
access_key_id: &str,
|
access_key_id: &str,
|
||||||
secret_access_key: &str,
|
secret_access_key: &str,
|
||||||
@@ -19,35 +19,16 @@ pub async fn make_ecr_client(
|
|||||||
EcrClient::new(&config)
|
EcrClient::new(&config)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets a token docker login.
|
|
||||||
///
|
|
||||||
/// Requires the aws cli be installed on the host
|
|
||||||
#[tracing::instrument(skip(access_key_id, secret_access_key))]
|
#[tracing::instrument(skip(access_key_id, secret_access_key))]
|
||||||
pub async fn get_ecr_token(
|
pub async fn maybe_create_repo(
|
||||||
region: &str,
|
repo: &str,
|
||||||
|
region: String,
|
||||||
access_key_id: &str,
|
access_key_id: &str,
|
||||||
secret_access_key: &str,
|
secret_access_key: &str,
|
||||||
) -> anyhow::Result<String> {
|
|
||||||
let log = async_run_command(&format!(
|
|
||||||
"AWS_ACCESS_KEY_ID={access_key_id} AWS_SECRET_ACCESS_KEY={secret_access_key} aws ecr get-login-password --region {region}"
|
|
||||||
))
|
|
||||||
.await;
|
|
||||||
|
|
||||||
if log.success() {
|
|
||||||
Ok(log.stdout)
|
|
||||||
} else {
|
|
||||||
Err(
|
|
||||||
anyhow!("stdout: {} | stderr: {}", log.stdout, log.stderr)
|
|
||||||
.context("failed to get aws ecr login token"),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tracing::instrument(skip(client))]
|
|
||||||
pub async fn maybe_create_repo(
|
|
||||||
client: &EcrClient,
|
|
||||||
repo: &str,
|
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
|
let client =
|
||||||
|
make_ecr_client(region, access_key_id, secret_access_key).await;
|
||||||
|
|
||||||
let existing = client
|
let existing = client
|
||||||
.describe_repositories()
|
.describe_repositories()
|
||||||
.send()
|
.send()
|
||||||
@@ -75,3 +56,27 @@ pub async fn maybe_create_repo(
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets a token docker login.
|
||||||
|
///
|
||||||
|
/// Requires the aws cli be installed on the host
|
||||||
|
#[tracing::instrument(skip(access_key_id, secret_access_key))]
|
||||||
|
pub async fn get_ecr_token(
|
||||||
|
region: &str,
|
||||||
|
access_key_id: &str,
|
||||||
|
secret_access_key: &str,
|
||||||
|
) -> anyhow::Result<String> {
|
||||||
|
let log = async_run_command(&format!(
|
||||||
|
"AWS_ACCESS_KEY_ID={access_key_id} AWS_SECRET_ACCESS_KEY={secret_access_key} aws ecr get-login-password --region {region}"
|
||||||
|
))
|
||||||
|
.await;
|
||||||
|
|
||||||
|
if log.success() {
|
||||||
|
Ok(log.stdout)
|
||||||
|
} else {
|
||||||
|
Err(
|
||||||
|
anyhow!("stdout: {} | stderr: {}", log.stdout, log.stderr)
|
||||||
|
.context("failed to get aws ecr login token"),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1 +1,2 @@
|
|||||||
pub mod ec2;
|
pub mod ec2;
|
||||||
|
pub mod ecr;
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ monitor_client = { workspace = true, features = ["docker"] }
|
|||||||
periphery_client.workspace = true
|
periphery_client.workspace = true
|
||||||
formatting.workspace = true
|
formatting.workspace = true
|
||||||
command.workspace = true
|
command.workspace = true
|
||||||
aws_ecr.workspace = true
|
|
||||||
logger.workspace = true
|
logger.workspace = true
|
||||||
git.workspace = true
|
git.workspace = true
|
||||||
# mogh
|
# mogh
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use anyhow::Context;
|
|||||||
use command::run_monitor_command;
|
use command::run_monitor_command;
|
||||||
use formatting::format_serror;
|
use formatting::format_serror;
|
||||||
use monitor_client::entities::{
|
use monitor_client::entities::{
|
||||||
build::{Build, BuildConfig, ImageRegistry},
|
build::{Build, BuildConfig},
|
||||||
config::core::AwsEcrConfig,
|
config::core::AwsEcrConfig,
|
||||||
get_image_name, optional_string, to_monitor_name,
|
get_image_name, optional_string, to_monitor_name,
|
||||||
update::Log,
|
update::Log,
|
||||||
@@ -68,11 +68,6 @@ pub async fn build(
|
|||||||
|
|
||||||
let name = to_monitor_name(name);
|
let name = to_monitor_name(name);
|
||||||
|
|
||||||
// Only needed for aws ecr
|
|
||||||
maybe_create_repo(&name, image_registry, aws_ecr)
|
|
||||||
.await
|
|
||||||
.context("failed to create new repo for the build")?;
|
|
||||||
|
|
||||||
// Get paths
|
// Get paths
|
||||||
let build_dir =
|
let build_dir =
|
||||||
periphery_config().repo_dir.join(&name).join(build_path);
|
periphery_config().repo_dir.join(&name).join(build_path);
|
||||||
@@ -82,7 +77,7 @@ pub async fn build(
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Get command parts
|
// Get command parts
|
||||||
let image_name = get_image_name(build, |_| aws_ecr)
|
let image_name = get_image_name(build, |_| aws_ecr.cloned())
|
||||||
.context("failed to make image name")?;
|
.context("failed to make image name")?;
|
||||||
let build_args = parse_build_args(build_args);
|
let build_args = parse_build_args(build_args);
|
||||||
let labels = parse_labels(labels);
|
let labels = parse_labels(labels);
|
||||||
@@ -145,33 +140,3 @@ fn parse_build_args(build_args: &[EnvironmentVar]) -> String {
|
|||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join("")
|
.join("")
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(skip_all)]
|
|
||||||
async fn maybe_create_repo(
|
|
||||||
name: &str,
|
|
||||||
image_registry: &ImageRegistry,
|
|
||||||
aws_ecr: Option<&AwsEcrConfig>,
|
|
||||||
) -> anyhow::Result<()> {
|
|
||||||
match image_registry {
|
|
||||||
ImageRegistry::AwsEcr(label) => {
|
|
||||||
let AwsEcrConfig {
|
|
||||||
region,
|
|
||||||
access_key_id,
|
|
||||||
secret_access_key,
|
|
||||||
..
|
|
||||||
} = aws_ecr.with_context(|| {
|
|
||||||
format!("did not find any aws ecr config for {label}")
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let client = aws_ecr::make_ecr_client(
|
|
||||||
region.to_string(),
|
|
||||||
access_key_id,
|
|
||||||
secret_access_key,
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
aws_ecr::maybe_create_repo(&client, name).await
|
|
||||||
}
|
|
||||||
_ => Ok(()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -76,26 +76,12 @@ pub async fn docker_login(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImageRegistry::AwsEcr(label) => {
|
ImageRegistry::AwsEcr(label) => {
|
||||||
let AwsEcrConfig {
|
let AwsEcrConfig { region, account_id } = aws_ecr
|
||||||
region,
|
|
||||||
account_id,
|
|
||||||
access_key_id,
|
|
||||||
secret_access_key,
|
|
||||||
} = aws_ecr.with_context(|| {
|
|
||||||
format!("Could not find aws ecr config for label {label}")
|
|
||||||
})?;
|
|
||||||
let registry_token = match registry_token {
|
|
||||||
Some(token) => token.to_string(),
|
|
||||||
None => aws_ecr::get_ecr_token(
|
|
||||||
region,
|
|
||||||
access_key_id,
|
|
||||||
secret_access_key,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
.with_context(|| {
|
.with_context(|| {
|
||||||
format!("failed to get aws ecr token for {label}")
|
format!("Could not find aws ecr config for label {label}")
|
||||||
})?,
|
})?;
|
||||||
};
|
let registry_token = registry_token
|
||||||
|
.context("aws ecr build missing registry token from core")?;
|
||||||
let log = async_run_command(&format!("docker login {account_id}.dkr.ecr.{region}.amazonaws.com -u AWS -p {registry_token}")).await;
|
let log = async_run_command(&format!("docker login {account_id}.dkr.ecr.{region}.amazonaws.com -u AWS -p {registry_token}")).await;
|
||||||
if log.success() {
|
if log.success() {
|
||||||
Ok(true)
|
Ok(true)
|
||||||
|
|||||||
@@ -397,7 +397,7 @@ pub struct CoreConfig {
|
|||||||
|
|
||||||
/// Configure aws ecr registries.
|
/// Configure aws ecr registries.
|
||||||
#[serde(default, alias = "aws_ecr_registry")]
|
#[serde(default, alias = "aws_ecr_registry")]
|
||||||
pub aws_ecr_registries: HashMap<String, AwsEcrConfig>,
|
pub aws_ecr_registries: HashMap<String, AwsEcrConfigWithCredentials>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_title() -> String {
|
fn default_title() -> String {
|
||||||
@@ -538,7 +538,7 @@ pub struct HetznerCredentials {
|
|||||||
|
|
||||||
/// Provide configuration for an Aws Ecr registry.
|
/// Provide configuration for an Aws Ecr registry.
|
||||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||||
pub struct AwsEcrConfig {
|
pub struct AwsEcrConfigWithCredentials {
|
||||||
/// The Aws region
|
/// The Aws region
|
||||||
pub region: String,
|
pub region: String,
|
||||||
/// The Aws account id
|
/// The Aws account id
|
||||||
@@ -548,3 +548,21 @@ pub struct AwsEcrConfig {
|
|||||||
/// The Aws SECRET_ACCESS_KEY
|
/// The Aws SECRET_ACCESS_KEY
|
||||||
pub secret_access_key: String,
|
pub secret_access_key: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Provide configuration for an Aws Ecr registry.
|
||||||
|
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||||
|
pub struct AwsEcrConfig {
|
||||||
|
/// The Aws region
|
||||||
|
pub region: String,
|
||||||
|
/// The Aws account id
|
||||||
|
pub account_id: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AwsEcrConfig {
|
||||||
|
pub fn from(config: &AwsEcrConfigWithCredentials) -> AwsEcrConfig {
|
||||||
|
AwsEcrConfig {
|
||||||
|
region: config.region.to_string(),
|
||||||
|
account_id: config.account_id.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -107,13 +107,13 @@ pub fn optional_string(string: &str) -> Option<String> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_image_name<'a, 'b>(
|
pub fn get_image_name(
|
||||||
build::Build {
|
build::Build {
|
||||||
name,
|
name,
|
||||||
config: build::BuildConfig { image_registry, .. },
|
config: build::BuildConfig { image_registry, .. },
|
||||||
..
|
..
|
||||||
}: &'a build::Build,
|
}: &build::Build,
|
||||||
aws_ecr: impl FnOnce(&'a String) -> Option<&'b AwsEcrConfig>,
|
aws_ecr: impl FnOnce(&String) -> Option<AwsEcrConfig>,
|
||||||
) -> anyhow::Result<String> {
|
) -> anyhow::Result<String> {
|
||||||
let name = to_monitor_name(name);
|
let name = to_monitor_name(name);
|
||||||
let name = match image_registry {
|
let name = match image_registry {
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "aws_ecr"
|
|
||||||
version.workspace = true
|
|
||||||
edition.workspace = true
|
|
||||||
authors.workspace = true
|
|
||||||
license.workspace = true
|
|
||||||
repository.workspace = true
|
|
||||||
homepage.workspace = true
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
run_command.workspace = true
|
|
||||||
#
|
|
||||||
aws-sdk-ecr.workspace = true
|
|
||||||
aws-config.workspace = true
|
|
||||||
tracing.workspace = true
|
|
||||||
anyhow.workspace = true
|
|
||||||
Reference in New Issue
Block a user