Skip to content

Commit 28f670a

Browse files
authored
feat: --skip-dependency-resolution for config install (#34)
1 parent 883a11e commit 28f670a

2 files changed

Lines changed: 62 additions & 50 deletions

File tree

README.md

Lines changed: 20 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -147,44 +147,14 @@ How it works:
147147
- Applies a GitHub `ProviderConfig` named `default` unless `--refresh` is used.
148148
- Supports overrides for namespace, Secret name, ProviderConfig name, provider name, and provider package.
149149

150-
## Quick Start
151-
152-
```bash
153-
# Build and load a Crossplane configuration package from an Upbound-format XRD project
154-
hops config install --path /path/to/project
155-
156-
# Build from a GitHub repo containing an Upbound-format XRD project
157-
hops config install --repo hops-ops/helm-certmanager
158-
159-
# Force reload from source (deletes existing ConfigurationRevision(s) first)
160-
hops config install --repo hops-ops/helm-certmanager --reload
161-
162-
# Apply a pinned remote package version directly (no clone/build)
163-
hops config install --repo hops-ops/helm-certmanager --version v0.1.0
164-
165-
# Remove a configuration and prune orphaned package dependencies
166-
hops config uninstall --repo hops-ops/helm-certmanager
167-
168-
# Generate apis/*/configuration.yaml from upbound.yaml for validation
169-
hops validate generate-configuration --path /path/to/project
170-
171-
# Observe an existing XR into a manifest
172-
hops xr observe --kind AutoEKSCluster --name pat-local --namespace default --aws-region us-east-2
173-
174-
# Render adoption patches for managed resources under an existing XR
175-
hops xr adopt --kind AutoEKSCluster --name pat-local --namespace default
176-
177-
# Convert an observed/adopted XR into a managed manifest
178-
hops xr manage --kind AutoEKSCluster --name pat-local --namespace default
179-
180-
# Render patches that remove Delete from management policies
181-
hops xr orphan --kind AutoEKSCluster --name pat-local --namespace default
182-
```
183-
184150
## Config packages
185151

186152
`config install` and `config uninstall` operate on the currently connected Kubernetes cluster.
187-
`config install` expects an Upbound-format XRD project when building from source via `--path` or `--repo`.
153+
154+
There are two different `config install` modes:
155+
156+
- Source-build mode via `--path` or `--repo` builds an Upbound-format XRD project locally, pushes the package through the local registry flow, and is intended for a local control plane started with `hops local start`.
157+
- Remote-package mode via `--repo ... --version ...` skips the build and applies a pinned package reference directly, so it can work against non-local connected clusters too.
188158

189159
Common install flows:
190160

@@ -196,23 +166,26 @@ hops config install
196166
hops config install --path /path/to/project
197167

198168
# Build from a cached GitHub repo checkout containing an Upbound-format XRD project
199-
hops config install --repo hops-ops/helm-certmanager
169+
hops config install --repo hops-ops/aws-auto-eks-cluster
200170

201171
# Force a source reload before re-applying
202-
hops config install --repo hops-ops/helm-certmanager --reload
172+
hops config install --repo hops-ops/aws-auto-eks-cluster --reload
173+
174+
# Set spec.skipDependencyResolution=true on the generated Configuration
175+
hops config install --path /path/to/project --skip-dependency-resolution
203176

204177
# Apply a pinned remote package directly from ghcr.io
205-
hops config install --repo hops-ops/helm-certmanager --version v0.1.0
178+
hops config install --repo hops-ops/aws-auto-eks-cluster --version v0.11.0
206179
```
207180

208181
Common uninstall flows:
209182

210183
```bash
211184
# Remove by explicit configuration name
212-
hops config uninstall --name hops-ops-helm-certmanager
185+
hops config uninstall --name hops-ops-aws-auto-eks-cluster
213186

214187
# Remove by repo slug
215-
hops config uninstall --repo hops-ops/helm-certmanager
188+
hops config uninstall --repo hops-ops/aws-auto-eks-cluster
216189

217190
# Remove configurations derived from local build artifacts
218191
hops config uninstall --path /path/to/project
@@ -221,6 +194,7 @@ hops config uninstall --path /path/to/project
221194
Notes:
222195

223196
- `--reload` only applies to source installs: `--path` or `--repo` without `--version`.
197+
- `--skip-dependency-resolution` sets `spec.skipDependencyResolution=true` on the generated `Configuration`.
224198
- `config install --repo ... --version ...` skips clone/build and applies the remote package directly.
225199
- `config uninstall --repo ...` derives the configuration name as `<org>-<repo>`.
226200

@@ -244,21 +218,26 @@ Notes:
244218
- Prompts for confirmation, then runs `brew uninstall colima`.
245219
- `config install [--path <PATH>] [--reload]`
246220
- Targets the currently connected Kubernetes cluster
221+
- Source-build mode intended for a local control plane because it depends on the local registry flow
247222
- Runs `up project build` in `PATH` (defaults to current directory)
248223
- Loads generated `.uppkg` artifacts from `<PATH>/_output`
249224
- Pushes package images to the registry exposed at `localhost:30500`
250225
- Applies Crossplane `Configuration` resources pointing at `registry.crossplane-system.svc.cluster.local:5000/...`
226+
- Supports `--skip-dependency-resolution`
251227
- `config install --repo <org/repo> [--reload]`
228+
- Source-build mode intended for a local control plane because it depends on the local registry flow
252229
- Uses local repo cache at `~/.hops/local/repo-cache/<org>/<repo>`
253230
- Clones on first use, then fetches/pulls on subsequent runs
254231
- Runs the same build/load/push/apply flow as `--path`
255232
- `--reload`
256233
- Forces source-based config install (`--path` or `--repo` without `--version`) to delete existing `ConfigurationRevision` resources and matching `Function`/`FunctionRevision` package resources from the same sources, then re-apply the `Configuration`
257234
- Useful when re-running a config and you want Crossplane to re-create the current revision from source
258235
- `config install --repo <org/repo> --version <tag>`
236+
- Remote-package mode that can target any connected cluster
259237
- Skips clone/build and applies `Configuration` with package `ghcr.io/<org>/<repo>:<tag>`
260-
- Uses configuration name `<org>-<repo>` (for example `hops-ops-helm-certmanager`)
238+
- Uses configuration name `<org>-<repo>` (for example `hops-ops-aws-auto-eks-cluster`)
261239
- Does not support `--reload`
240+
- Supports `--skip-dependency-resolution`
262241
- `config uninstall --name <configuration-name>`
263242
- Deletes the target `Configuration`
264243
- Waits for package lock reconciliation

src/commands/config/install.rs

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ pub struct ConfigArgs {
4141
/// Force reload from source by recreating ConfigurationRevision(s) before apply (path/repo only)
4242
#[arg(long, conflicts_with = "version")]
4343
pub reload: bool,
44+
45+
/// Set spec.skipDependencyResolution=true on the generated Configuration
46+
#[arg(long)]
47+
pub skip_dependency_resolution: bool,
4448
}
4549

4650
#[derive(Clone, Debug)]
@@ -127,9 +131,15 @@ pub fn run(args: &ConfigArgs) -> Result<(), Box<dyn Error>> {
127131
validate_reload_args(args)?;
128132

129133
match (args.repo.as_deref(), args.version.as_deref()) {
130-
(Some(repo), Some(version)) => apply_repo_version(repo, version),
131-
(Some(repo), None) => run_repo_clone(repo, args.reload),
132-
(None, _) => run_local_path(args.path.as_deref().unwrap_or("."), args.reload),
134+
(Some(repo), Some(version)) => {
135+
apply_repo_version(repo, version, args.skip_dependency_resolution)
136+
}
137+
(Some(repo), None) => run_repo_clone(repo, args.reload, args.skip_dependency_resolution),
138+
(None, _) => run_local_path(
139+
args.path.as_deref().unwrap_or("."),
140+
args.reload,
141+
args.skip_dependency_resolution,
142+
),
133143
}
134144
}
135145

@@ -140,10 +150,18 @@ fn validate_reload_args(args: &ConfigArgs) -> Result<(), Box<dyn Error>> {
140150
Ok(())
141151
}
142152

143-
fn run_repo_clone(repo: &str, reload: bool) -> Result<(), Box<dyn Error>> {
153+
fn run_repo_clone(
154+
repo: &str,
155+
reload: bool,
156+
skip_dependency_resolution: bool,
157+
) -> Result<(), Box<dyn Error>> {
144158
let spec = parse_repo_spec(repo)?;
145159
let cache_path = ensure_cached_repo_checkout(&spec)?;
146-
run_local_path(&cache_path.to_string_lossy(), reload)
160+
run_local_path(
161+
&cache_path.to_string_lossy(),
162+
reload,
163+
skip_dependency_resolution,
164+
)
147165
}
148166

149167
fn ensure_cached_repo_checkout(spec: &RepoSpec) -> Result<PathBuf, Box<dyn Error>> {
@@ -202,7 +220,11 @@ fn refresh_cached_repo(cache_path: &Path) -> Result<(), Box<dyn Error>> {
202220
Ok(())
203221
}
204222

205-
fn apply_repo_version(repo: &str, version: &str) -> Result<(), Box<dyn Error>> {
223+
fn apply_repo_version(
224+
repo: &str,
225+
version: &str,
226+
skip_dependency_resolution: bool,
227+
) -> Result<(), Box<dyn Error>> {
206228
let spec = parse_repo_spec(repo)?;
207229
let version = version.trim();
208230
if version.is_empty() {
@@ -215,7 +237,12 @@ fn apply_repo_version(repo: &str, version: &str) -> Result<(), Box<dyn Error>> {
215237
sanitize_name_component(&spec.org),
216238
sanitize_name_component(&spec.repo)
217239
);
218-
apply_configuration(&config_name, &package_ref, false, false)
240+
apply_configuration(
241+
&config_name,
242+
&package_ref,
243+
skip_dependency_resolution,
244+
false,
245+
)
219246
}
220247

221248
fn parse_repo_spec(repo: &str) -> Result<RepoSpec, Box<dyn Error>> {
@@ -261,7 +288,11 @@ fn sanitize_name_component(input: &str) -> String {
261288
}
262289
}
263290

264-
fn run_local_path(path: &str, reload: bool) -> Result<(), Box<dyn Error>> {
291+
fn run_local_path(
292+
path: &str,
293+
reload: bool,
294+
skip_dependency_resolution: bool,
295+
) -> Result<(), Box<dyn Error>> {
265296
let dir = Path::new(path);
266297
if !dir.is_dir() {
267298
return Err(format!("{} is not a directory", path).into());
@@ -452,7 +483,7 @@ spec:
452483
for pull_ref in &config_pull_refs {
453484
let (img_path, _) = split_ref(pull_ref);
454485
let name = img_path.rsplit('/').next().unwrap_or(img_path);
455-
apply_configuration(name, pull_ref, false, reload)?;
486+
apply_configuration(name, pull_ref, skip_dependency_resolution, reload)?;
456487
}
457488

458489
Ok(())
@@ -1121,6 +1152,7 @@ spec:
11211152
repo: Some("hops-ops/helm-certmanager".to_string()),
11221153
version: Some("v0.1.0".to_string()),
11231154
reload: true,
1155+
skip_dependency_resolution: false,
11241156
};
11251157
assert!(validate_reload_args(&args).is_err());
11261158
}
@@ -1132,6 +1164,7 @@ spec:
11321164
repo: None,
11331165
version: None,
11341166
reload: true,
1167+
skip_dependency_resolution: false,
11351168
};
11361169
assert!(validate_reload_args(&args).is_ok());
11371170
}

0 commit comments

Comments
 (0)