-
Notifications
You must be signed in to change notification settings - Fork 35
Upgrade examples on the new docs #275
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
85b2a82
143118b
7fba00e
03d78c5
d539552
1a0ff99
bdda058
d4afb9a
d3b5479
dd0a1a9
663cf36
ca86066
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| --- | ||
| title: "Package Lifecycle" | ||
| type: docs | ||
| weight: 3 | ||
| description: | ||
| --- | ||
|
|
||
| ## Package Lifecycle Workflow | ||
|
|
||
| Packages managed by Porch progress through several states, from creation to final publication. This workflow ensures that packages are reviewed and approved before they are published and consumed. | ||
|
|
||
| The typical lifecycle of a package is as follows: | ||
|
|
||
| 1. **Draft:** A user initializes a new package or clones an existing one. The package is in a `Draft` state, allowing the user to make changes freely in their local workspace. | ||
| 2. **Proposed:** Once the changes are ready for review, the user pushes the package, which transitions it to the `Proposed` state. In this stage, the package is available for review by other team members. | ||
| 3. **Review and Approval:** | ||
| * **Approved:** If the package is approved, it is ready to be published. | ||
| * **Rejected:** If changes are required, the package is rejected. The user must pull the package, make the necessary modifications, and re-propose it for another review. | ||
| 4. **Published:** After approval, the package is published. Published packages are considered stable and are available for deployment and consumption by other systems or clusters. They typically become the "latest" version of a package. | ||
|
|
||
|  |
This file was deleted.
lapentad marked this conversation as resolved.
Show resolved
Hide resolved
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,16 +1,307 @@ | ||
| --- | ||
| title: "Upgrading Packages" | ||
| title: "Upgrading Package Revisions" | ||
| type: docs | ||
| weight: 6 | ||
| description: | ||
| description: "A guide to upgrade package revisions using Porch and porchctl" | ||
| --- | ||
|
|
||
| ## Lorem Ipsum | ||
| The package upgrade feature in Porch is a powerful mechanism for keeping deployed packages (downstream) up-to-date with their source blueprints (upstream). This guide walks through the entire workflow, from creating packages to performing an upgrade, with a special focus on the different upgrade scenarios and merge strategies. | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Link to the porchctl guide here somewhere /docs/neo-porch/7_cli_api/relevant_old_docs/porchctl-cli-guide/#package-upgrade |
||
|
|
||
| [UPGRADE EXAMPLES] [ALL THE DIFF SCENARIOS] [THIS IS THE MOST COMPLEX PART] [IT NEEDS TO BE VERY SPECIFIC ON WHAT DO/DONT WE SUPPORT] [] | ||
| For detailed command reference, see the [porchctl CLI guide]({{% relref "/docs/neo-porch/7_cli_api/relevant_old_docs/porchctl-cli-guide/#package-upgrade" %}}). | ||
|
|
||
| - [CREATE A GENERIC PACKAGE AND RUN IT THROUGH THE DIFFERENT UPGRADES TO SHOW HOW THEY WORK AND CHANGE] | ||
| - in upgrade scenario we expect that we have NEW BLUEPRINT IS PUBLISHED → DEPLOYMENT PACKAGE CAN BE UPGRADED IF IT WAS BASED ON THAT BLUEPRINT (AKA THE UPSTREAM OF THIS PACKAGE POINTS AT THAT BLUEPRINT). assuming 2 repositories | ||
| - [RESOURCE MERGE] IS A STRUCTURAL 3 WAY MERGE → HAS CONTEXT OF THE STRUCTURE OF THE FILES -> | ||
| - [COPY MERGE] IS A FILE REPLACEMENT STRATEGY → USEFUL WHEN YOU DONT NEED PORCH TO BE AWARE OF THE CONTENT OF THE FILES ESPECIALLY IF THERE IS CONTENT INSIDE THE FILES THAT DO NOT COMPLY WITH KUSTOMIZE. | ||
| - [OTHER STRATEGIES] … | ||
| ## Prerequisites | ||
|
|
||
| * Porch installed in your Kubernetes cluster, along with its CLI `porchctl`. [Setup Guide]({{% relref "/docs/neo-porch/3_getting_started/installing-porch.md" %}}) | ||
| * A Git Repository registered with Porch, in this example it's assumed that the Porch-Repository's name is "porch-test". [Repository Guide]({{% relref "/docs/neo-porch/4_tutorials_and_how-tos/setting-up-repositories" %}}) | ||
|
|
||
| ## Key Concepts | ||
|
|
||
| To understand the upgrade process, it's essential to be familiar with the three states of a package during a merge operation: | ||
|
|
||
| * **Original:** The state of the package when it was first cloned from the blueprint (e.g., `Blueprint v1`). This serves as the common ancestor for the merge. | ||
| * **Upstream:** The new, updated version of the source blueprint (e.g., `Blueprint v2`). This contains the changes you want to incorporate. | ||
| * **Local:** The current state of your deployment package, including any customizations you have applied since it was cloned. | ||
|
|
||
| The upgrade process combines changes from the **Upstream** blueprint with your **Local** customizations, using the **Original** version as a base to resolve differences. | ||
|
|
||
| ## End-to-End Upgrade Example | ||
|
|
||
| This example demonstrates the complete process of creating, customizing, and upgrading a package. | ||
|
|
||
| ### Step 1: Create a Base Blueprint Package (revision 1) | ||
|
|
||
| Create the initial revision of our blueprint. This will be the "upstream" source for our deployment package. | ||
|
|
||
| ```bash | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These are fine but would it be better to split them out to single commands, with an example output? |
||
| # Initialize a new package draft named 'blueprint' in the 'porch-test' repository | ||
| porchctl rpkg init blueprint --namespace=porch-demo --repository=porch-test --workspace=1 | ||
| ``` | ||
|
|
||
| ```bash | ||
| # Propose the draft for review | ||
| porchctl rpkg propose porch-test.blueprint.1 --namespace=porch-demo | ||
| ``` | ||
|
|
||
| ```bash | ||
| # Approve and publish the package, making it available as revision 1 | ||
| porchctl rpkg approve porch-test.blueprint.1 --namespace=porch-demo | ||
| ``` | ||
|
|
||
| ### Step 2: Create a New Blueprint Package Revision (revision 2) | ||
|
|
||
| Create a new revision of the blueprint to simulate an update. In this case, we add a new ConfigMap. | ||
|
|
||
| ```bash | ||
| # Create a new draft (v2) by copying v1 | ||
| porchctl rpkg copy porch-test.blueprint.1 --namespace=porch-demo --workspace=2 | ||
|
|
||
| # Pull the contents of the new draft locally to make changes | ||
| porchctl rpkg pull porch-test.blueprint.2 --namespace=porch-demo ./tmp/blueprint-v2 | ||
|
|
||
| # Add a new resource file to the package | ||
| kubectl create configmap test-cm --dry-run=client -o yaml > ./tmp/blueprint-v2/new-configmap.yaml | ||
|
|
||
| # Push the local changes back to the Porch draft | ||
| porchctl rpkg push porch-test.blueprint.2 --namespace=porch-demo ./tmp/blueprint-v2 | ||
|
|
||
| # Propose and approve the new version | ||
| porchctl rpkg propose porch-test.blueprint.2 --namespace=porch-demo | ||
| porchctl rpkg approve porch-test.blueprint.2 --namespace=porch-demo | ||
| ``` | ||
| At this point, we have two published blueprint versions: `v1` (the original) and `v2` (with the new ConfigMap). | ||
|
|
||
| ### Step 3: Clone Blueprint revision 1 into a Deployment Package | ||
|
|
||
| Clone the blueprint to create a "downstream" deployment package. | ||
|
|
||
| ```bash | ||
| # Clone blueprint v1 to create a new deployment package | ||
| porchctl rpkg clone porch-test.blueprint.1 --namespace=porch-demo --repository=porch-test --workspace=1 deployment | ||
|
|
||
| # Pull the new deployment package locally to apply customizations | ||
| porchctl rpkg pull porch-test.deployment.1 --namespace=porch-demo ./tmp/deployment-v1 | ||
|
|
||
| # Apply a local customization (e.g., add an annotation to the Kptfile) | ||
| kpt fn eval --image gcr.io/kpt-fn/set-annotations:v0.1.4 ./tmp/deployment-v1/Kptfile -- kpt.dev/annotation=true | ||
|
|
||
| # Push the local changes back to Porch | ||
| porchctl rpkg push porch-test.deployment.1 --namespace=porch-demo ./tmp/deployment-v1 | ||
|
|
||
| # Propose and approve the deployment package | ||
| porchctl rpkg propose porch-test.deployment.1 --namespace=porch-demo | ||
| porchctl rpkg approve porch-test.deployment.1 --namespace=porch-demo | ||
| ``` | ||
|
|
||
| ### Step 4: Discover and Perform the Upgrade | ||
|
|
||
| Our deployment package is based on `blueprint.1`, but we know `blueprint.2` is available. We can discover and apply this upgrade. | ||
|
|
||
| ```bash | ||
| # Discover available upgrades for packages cloned from 'upstream' repositories | ||
| porchctl rpkg upgrade --discover=upstream | ||
| # This will list 'porch-test.deployment.1' as having an available upgrade to revision 2. | ||
|
|
||
| # Upgrade the deployment package to revision 2 of its upstream blueprint | ||
| # This creates a new draft package: 'porch-test.deployment.2' | ||
| porchctl rpkg upgrade porch-test.deployment.1 --namespace=porch-demo --revision=2 --workspace=2 | ||
|
|
||
| # Propose and approve the upgraded package | ||
| porchctl rpkg propose porch-test.deployment.2 --namespace=porch-demo | ||
| porchctl rpkg approve porch-test.deployment.2 --namespace=porch-demo | ||
| ``` | ||
|
|
||
| After approval, `porch-test.deployment.2` is the new, published deployment package. It now contains: | ||
| 1. The `new-configmap.yaml` from the upstream `blueprint.2`. | ||
| 2. The local `kpt.dev/annotation=true` customization applied in Step 3. | ||
|
|
||
| ## Understanding Merge Strategies | ||
|
|
||
|  | ||
|
|
||
| **Schema Explanation:** | ||
| The diagram above illustrates the package upgrade workflow in Porch: | ||
|
|
||
| 1. **CLONE**: A deployment package (Deployment.v1) is initially cloned from a blueprint (Blueprint.v1) in the blueprints repository | ||
| 2. **COPY**: The blueprint evolves to a new version (Blueprint.v2) with additional features or fixes | ||
| 3. **UPGRADE**: The deployment package is upgraded to incorporate changes from the new blueprint version, creating Deployment.v2 | ||
|
|
||
| The dashed line shows the relationship between the new blueprint version and the upgrade process, indicating that the upgrade "uses the new blueprint" as its source for changes. | ||
|
|
||
| The outcome of an upgrade depends on the changes made in the upstream blueprint and the local deployment package, combined with the chosen merge strategy. You can specify a strategy using the `--strategy` flag (e.g., `porchctl rpkg upgrade ... --strategy=copy-merge`). | ||
|
|
||
| ### Merge Strategy Comparison | ||
|
|
||
| <table class="table"> | ||
| <thead class="table-light"> | ||
| <tr> | ||
| <th scope="col" class="table-light">Scenario</th> | ||
| <th scope="col">resource-merge (Default)</th> | ||
| <th scope="col">copy-merge</th> | ||
| <th scope="col">force-delete-replace</th> | ||
| <th scope="col">fast-forward</th> | ||
| </tr> | ||
| </thead> | ||
| <tbody> | ||
| <tr> | ||
| <th scope="row" class="table-light"><strong>File added in Upstream</strong></th> | ||
| <td>File is added to Local.</td> | ||
| <td>File is added to Local.</td> | ||
| <td>File is added to Local.</td> | ||
| <td>Fails (Local must be unchanged).</td> | ||
| </tr> | ||
| <tr> | ||
| <th scope="row" class="table-light"><strong>File modified in Upstream only</strong></th> | ||
| <td>Changes are applied to Local.</td> | ||
| <td>Upstream file overwrites Local file.</td> | ||
| <td>Upstream file overwrites Local file.</td> | ||
| <td>Fails (Local must be unchanged).</td> | ||
| </tr> | ||
| <tr> | ||
| <th scope="row" class="table-light"><strong>File modified in Local only</strong></th> | ||
| <td>Local changes are kept.</td> | ||
| <td>Local changes are kept.</td> | ||
| <td>Local changes are discarded; Upstream version is used.</td> | ||
| <td>Fails (Local must be unchanged).</td> | ||
| </tr> | ||
| <tr> | ||
| <th scope="row" class="table-light"><strong>File modified in both (no conflict)</strong></th> | ||
| <td>Both changes are merged.</td> | ||
| <td>Upstream file overwrites Local file.</td> | ||
| <td>Upstream file overwrites Local file.</td> | ||
| <td>Fails (Local must be unchanged).</td> | ||
| </tr> | ||
| <tr> | ||
| <th scope="row" class="table-light"><strong>File modified in both (conflict)</strong></th> | ||
| <td>Merge autoconflic resolution: always choose the new upstream version.</td> | ||
| <td>Upstream file overwrites Local file.</td> | ||
| <td>Upstream file overwrites Local file.</td> | ||
| <td>Fails (Local must be unchanged).</td> | ||
| </tr> | ||
| <tr> | ||
| <th scope="row" class="table-light"><strong>File deleted in Upstream</strong></th> | ||
| <td>File is deleted from Local.</td> | ||
| <td>File is deleted from Local.</td> | ||
| <td>File is deleted from Local.</td> | ||
| <td>Fails (Local must be unchanged).</td> | ||
| </tr> | ||
| <tr> | ||
| <th scope="row" class="table-light"><strong>Local package is unmodified</strong></th> | ||
| <td>Upgrade succeeds.</td> | ||
| <td>Upgrade succeeds.</td> | ||
| <td>Upgrade succeeds.</td> | ||
| <td>Upgrade succeeds.</td> | ||
| </tr> | ||
| </tbody> | ||
| </table> | ||
|
|
||
| ### Detailed Strategy Explanations | ||
|
|
||
| #### **resource-merge (Default)** | ||
| This is a structural 3-way merge designed for Kubernetes resources. It understands the structure of YAML files and attempts to intelligently merge changes from the upstream and local packages. | ||
|
|
||
| * **Use case:** This is the **recommended default strategy** for managing Kubernetes configuration. Use it when you want to preserve local customizations while incorporating upstream updates. | ||
|
|
||
| #### **copy-merge** | ||
| A file-level replacement strategy. For any file present in both local and upstream, the upstream version is used, overwriting local changes. Files that only exist locally are kept. | ||
|
|
||
| * **Use case:** When you trust the upstream source more than local changes or when Porch cannot parse the file contents (e.g., non-KRM files). | ||
|
|
||
| #### **force-delete-replace** | ||
| The most aggressive strategy. It completely discards the local package's contents and replaces them with the contents of the new upstream package. | ||
|
|
||
| * **Use case:** To completely reset a deployment package to a new blueprint version, abandoning all previous customizations. | ||
|
|
||
| #### **fast-forward** | ||
| A fail-fast safety check. The upgrade only succeeds if the local package has **zero modifications** compared to the original blueprint version it was cloned from. | ||
|
|
||
| * **Use case:** To guarantee that you are only upgrading unmodified packages, preventing accidental overwrites of important local customizations. | ||
|
|
||
| ## Practical examples: upgrade strategies in action | ||
|
|
||
| This section contains short, focused examples showing how each merge strategy behaves in realistic scenarios. Each example assumes you have a deployment package `porch-test.deployment.1` cloned from `porch-test.blueprint.1` and that `porch-test.blueprint.2` is available upstream. | ||
|
|
||
| ### Example A — resource-merge (default) | ||
|
|
||
| Scenario: Upstream adds a new ConfigMap and local changes added an annotation to Kptfile. `resource-merge` should apply the upstream addition while preserving the local annotation. | ||
|
|
||
| Commands: | ||
|
|
||
| ```bash | ||
| # discover available upgrades | ||
| porchctl rpkg upgrade --discover=upstream | ||
| ``` | ||
|
|
||
| ```bash | ||
| # perform upgrade using the default strategy | ||
| porchctl rpkg upgrade porch-test.deployment.1 --namespace=porch-demo --revision=2 --workspace=2 | ||
| ``` | ||
|
|
||
| Outcome: A new draft `porch-test.deployment.2` is created containing both the new `ConfigMap` and the local annotation. | ||
|
|
||
| ### Example B — copy-merge | ||
|
|
||
| Scenario: Upstream changes a file that the local package also modified, but you want the upstream version to win (file-level overwrite). | ||
|
|
||
| Commands: | ||
|
|
||
| ```bash | ||
| porchctl rpkg upgrade porch-test.deployment.1 --namespace=porch-demo --revision=2 --workspace=2 --strategy=copy-merge | ||
| ``` | ||
|
|
||
| Outcome: Files present in both upstream and local are replaced with the upstream copy. Files only present locally are preserved. | ||
|
|
||
| ### Example C — force-delete-replace | ||
|
|
||
| Scenario: The blueprint has diverged substantially; you want to reset the deployment package to exactly match upstream v2. | ||
|
|
||
| Commands: | ||
|
|
||
| ```bash | ||
| porchctl rpkg upgrade porch-test.deployment.1 --namespace=porch-demo --revision=2 --workspace=2 --strategy=force-delete-replace | ||
| ``` | ||
|
|
||
| Outcome: The new draft contains only the upstream contents; local customizations are discarded. | ||
|
|
||
| ### Example D — fast-forward | ||
|
|
||
| Scenario: You want to ensure upgrades are only applied to unmodified, pristine clones. | ||
|
|
||
| Commands: | ||
|
|
||
| ```bash | ||
| porchctl rpkg upgrade porch-test.deployment.1 --namespace=porch-demo --revision=2 --workspace=2 --strategy=fast-forward | ||
| ``` | ||
|
|
||
| Outcome: The upgrade succeeds only if `porch-test.deployment.1` has no local modifications compared to the original clone. If local changes exist, the command fails and reports the modifications that prevented a fast-forward. | ||
|
|
||
| ## Reference | ||
|
|
||
| ### Command Flags | ||
|
|
||
| The `porchctl rpkg upgrade` command has several key flags: | ||
lapentad marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| * `--workspace=<name>`: (Mandatory) The name for the new workspace where the upgraded package draft will be created. | ||
| * `--revision=<number>`: (Optional) The specific revision number of the upstream package to upgrade to. If not specified, Porch will automatically use the latest published revision. | ||
| * `--strategy=<strategy>`: (Optional) The merge strategy to use. Defaults to `resource-merge`. Options are `resource-merge`, `copy-merge`, `force-delete-replace`, `fast-forward`. | ||
|
|
||
| For more details, run `porchctl rpkg upgrade --help`. | ||
|
|
||
| ### Best Practices | ||
|
|
||
| * **Separate Repositories:** For better organization and access control, keep blueprint packages and deployment packages in separate Git repositories. | ||
| * **Understand Your Strategy:** Before upgrading, be certain which merge strategy fits your use case to avoid accidentally losing important local customizations. When in doubt, the default `resource-merge` is the safest and most intelligent option. | ||
|
|
||
| ### Cleanup | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice to have but prob not necessary. |
||
|
|
||
| To remove the packages created in this guide, you must first propose them for deletion and then perform the final deletion. | ||
|
|
||
| ```bash | ||
| # Clean up local temporary directory used in these examples | ||
| rm -rf ./tmp | ||
|
|
||
| # Propose all packages for deletion | ||
| porchctl rpkg propose-delete porch-test.blueprint.1 porch-test.blueprint.2 porch-test.deployment.1 porch-test.deployment.2 --namespace=porch-demo | ||
|
|
||
| # Delete the packages | ||
| porchctl rpkg delete porch-test.blueprint.1 porch-test.blueprint.2 porch-test.deployment.1 porch-test.deployment.2 --namespace=porch-demo | ||
| ``` | ||
Uh oh!
There was an error while loading. Please reload this page.