Skip to content
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

Remove the ComponentStatus resource type #1234

Merged
merged 1 commit into from
Aug 4, 2020

Conversation

lblackstone
Copy link
Member

Proposed changes

The core/v1:ComponentStatus resource only supports the GET
operation, and is deprecated/unsupported [1]. Remove it from
our SDKs since it's not useful in this form.

[1] kubernetes/kubernetes#93570

Related issues (optional)

Fix #1233

The core/v1:ComponentStatus resource only supports the GET
operation, and is deprecated/unsupported [1]. Remove it from
our SDKs since it's not useful in this form.

[1] kubernetes/kubernetes#93570
Copy link
Contributor

@metral metral left a comment

Choose a reason for hiding this comment

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

LGTM overall.

Is it worth announcing this removal more broadly, in case there are users of it?

@lblackstone
Copy link
Member Author

Is it worth announcing this removal more broadly, in case there are users of it?

I tried using it, and couldn't get it to do anything since it doesn't support POST. I'd be surprised if anyone is using it.

@lblackstone lblackstone merged commit 4811a8d into master Aug 4, 2020
@pulumi-bot pulumi-bot deleted the lblackstone/remove-componentstatus branch August 4, 2020 23:32
t0yv0 added a commit that referenced this pull request Sep 12, 2023
<!--Thanks for your contribution. See [CONTRIBUTING](CONTRIBUTING.md)
    for Pulumi's contribution guidelines.

    Help us merge your changes more quickly by adding more details such
    as labels, milestones, and reviewers.-->

### Proposed changes

<!--Give us a brief description of what you've done and what it solves.
-->

The custom script called from custom Make had temporary modifications to
setup.py and pyproject.toml.
These are now upstreamed to pulumi/pkg and with version 3.81.0 this
happens automatically as part of code generation.
This PR removes temporary script code.

Fixes #2553 

Part of the rollout plain in pulumi/home#2883

### Related issues (optional)

<!--Refer to related PRs or issues: #1234, or 'Fixes #1234' or 'Closes
#1234'.
Or link to full URLs to issues or pull requests in other GitHub
repositories. -->
EronWright added a commit that referenced this pull request Sep 21, 2023
<!--Thanks for your contribution. See [CONTRIBUTING](CONTRIBUTING.md)
    for Pulumi's contribution guidelines.

    Help us merge your changes more quickly by adding more details such
    as labels, milestones, and reviewers.-->

### Proposed changes
<!--Give us a brief description of what you've done and what it solves.
-->

This PR improves the handling of the read-only metadata fields of
Kubernetes objects, such as `creationTimestamp` and `resourceVersion`.
The provider now ignores these fields when they appear as resource
inputs, to address a few quirks:
1. Unparseable values do not cause an API Server error during preview.
2. A subsequent refresh does not show a difference to the `__inputs`
property.
3. The behavior is now uniform for standard resource types and for
custom resource types.

An integration test is provided to show that such fields are ignored as
inputs, and are still available as outputs. Manual tests confirmed
identical behavior for custom resource objects.

### Related issues (optional)
Closes #2351

Related:
- #2511
- #2445

<!--Refer to related PRs or issues: #1234, or 'Fixes #1234' or 'Closes
#1234'.
Or link to full URLs to issues or pull requests in other GitHub
repositories. -->
EronWright added a commit that referenced this pull request Sep 29, 2023
<!--Thanks for your contribution. See [CONTRIBUTING](CONTRIBUTING.md)
    for Pulumi's contribution guidelines.

    Help us merge your changes more quickly by adding more details such
    as labels, milestones, and reviewers.-->

### Proposed changes
Closes #2485.

This PR implements cancelation for `Create` and `Update` operations on
the Helm Release resource. When the user presses ctrl-c, the Helm
operation is cancelled and the stack state is updated accordingly. This
is an improvement over the current behavior where the Helm release may
be orphaned by Pulumi.

A future enhancement would be to implement cancelation for the `Delete`
operation, once it becomes possible in the Helm v3 library (see
[PR](helm/helm#12109) and the `RunWithContext`
variants).

_Note: no new tests are provided because I don't see a way to simulate
cancelation using the integration test framework._

### Related issues (optional)

<!--Refer to related PRs or issues: #1234, or 'Fixes #1234' or 'Closes
#1234'.
Or link to full URLs to issues or pull requests in other GitHub
repositories. -->
Related to pulumi/pulumi#14057. It is safe to
merge this PR beforehand.
henry-fn added a commit to henry-fn/pulumi-kubernetes that referenced this pull request Oct 3, 2023
<!--Thanks for your contribution. See [CONTRIBUTING](CONTRIBUTING.md)
    for Pulumi's contribution guidelines.

    Help us merge your changes more quickly by adding more details such
    as labels, milestones, and reviewers.-->

### Proposed changes

This PR exposes the helm template `--kube-version` argument so it can be manually specified in situations when there is no access to the Kubernetes API server (e.g running a diff in CSA mode with no connection to the cluster).

Prior to this merge:
* If there were zero k8s contexts --> this field was unset meaning helm would default to some old version (1.20.0 at the time of writing) if it couldn't connect to the k8s context
* 1+ k8s contexts --> would always try to contact the API server to get the version leading to an error if the API server was unreachable.

This variable will override the behavior in either case, but is mostly useful in the first case or when the context in the second case is malformed / unreachable. 

### Related issues (optional)

<!--Refer to related PRs or issues: pulumi#1234, or 'Fixes pulumi#1234' or 'Closes pulumi#1234'.
    Or link to full URLs to issues or pull requests in other GitHub repositories. -->

Closes pulumi#2563
EronWright added a commit that referenced this pull request Oct 18, 2023
<!--Thanks for your contribution. See [CONTRIBUTING](CONTRIBUTING.md)
    for Pulumi's contribution guidelines.

    Help us merge your changes more quickly by adding more details such
    as labels, milestones, and reviewers.-->

### Proposed changes
Closes #2486 

This PR exposes the provider input properties as outputs, and normalizes
those inputs to provide the effective values. This opens up some new
scenarios:
1. Use the provider's namespace as an input property, in a uniform way.
2. A better experience when the ambient kubeconfig is changed; Pulumi
reports a diff to `namespace`, `context` or `cluster` as appropriate,
which helps to explain why downstream changes may be occurring.

### Detailed Changes

The following provider inputs are normalized such that they contain the
effective values in stack state:
1. `namespace` - normalized to contain the ambient namespace or
`default`.
2. `context`- normalized to contain the ambient context name.
3. `cluster` normalized to contain the ambient cluster name.

The `kubeconfig` property is not normalized, which means that the
application would need to manually load the ambient config. It seems
like a bad idea to normalize the `kubeconfig` for a few reasons:
1. it bloats the stack state to include the entire kubeconfig contents.
2. the kubeconfig may contain a secret in rare situations but isn't
modeled as a secret input.
6. the application can workaround it, since the raw output is now
available.

The Helm provider was simplified to always take the merged kubeconfig
(`apiConfig`) from the kube provider, as opposed to reloading it in some
cases. This should have no effect on the behavior.

Some minor improvements to kubeconfig loading logic:
1. Use a non-interactive loader for the kubeconfig, since the provider
is a non-interactive server (see [original
PR](e85e033#diff-5e83e1a18ae8dd9641b49e491350ae5b8afaf7fdb60dfcf4d4447a17e334e473R26)).
The rationale is to be consistent with the (newer) Helm code.
2. When the `kubeconfig` property is path-like, don't try to parse it as
content. This improves the error message.
3. Fallback to using the `default` namespace (as opposed to undefined)
for diff purposes when the config could not be loaded.

The special-case logic around 'replacement' was simplified to consider
only the normalized server name. That is, the provider recommends
replacement when the `name` field of the active server has changed. The
earlier code had major limitations - it didn't consider the ambient
kubeconfig, and didn't support kubeconfig paths.

### Testing
New tests were added and/or updated:
1. `TestProvider` - updated to verify that the provider's `namespace`
output property is useable as an input to other resources.
2. `TestProviderOutputs` - added to verify provider outputs and the
normalization logic.
3. `Test_loadKubeconfig` - added to verify kubeconfig loading/parsing
logic.

New utility code was developed for easily asserting that certain engine
events occurred during `ExtraRuntimeValidation`; see
`util.go#AssertEvents`.

### Example
Here's an example showing the use of the provider's new `namespace`
output property, and showing the improved change detection related to
the ambient namespace.

The program relies on the ambient kubeconfig, uses the ambient namespace
to create a `Deployment`, and binds the provider's `namespace` output
property to the stack outputs:
```yaml
name: issue-2486-yaml
runtime: yaml
description: A minimal Kubernetes Pulumi YAML program
outputs:
  namespace: ${k8s.namespace}
  deployment: ${deployment.metadata.namespace}/${deployment.metadata.name}
resources:
  k8s:
    type: pulumi:providers:kubernetes
  deployment:
    type: kubernetes:apps/v1:Deployment
    options:
      provider: ${k8s}
    properties:
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: nginx
        template:
          metadata:
            labels:
              app: nginx
          spec:
            containers:
            - image: nginx
              name: nginx
```

The procedure deploys the stack, changes the ambient namespace, and then
previews the changes:
```plain
❯ pulumi up -f
Updating (dev)

View in Browser (Ctrl+O): https://app.pulumi.com/eron-pulumi-corp/issue-2486-yaml/dev/updates/8

     Type                              Name                 Status              Info
 +   pulumi:pulumi:Stack               issue-2486-yaml-dev  created (3s)        4 warnings
 +   ├─ pulumi:providers:kubernetes    k8s                  created (0.12s)     
 +   └─ kubernetes:apps/v1:Deployment  deployment           created (2s)        

Outputs:
    deployment: "default/deployment-bf4abb76"
    namespace : "default"

Resources:
    + 3 created

Duration: 4s

❯ kubectl config set-context --current --namespace eron
Context "docker-desktop" modified.

❯ pulumi preview
Previewing update (dev)

View in Browser (Ctrl+O): https://app.pulumi.com/eron-pulumi-corp/issue-2486-yaml/dev/previews/2cf2c42a-0a95-42b3-b193-ffca7f401fc7

     Type                              Name                 Plan        Info
     pulumi:pulumi:Stack               issue-2486-yaml-dev              4 warnings
 ~   ├─ pulumi:providers:kubernetes    k8s                  update      [diff: ~namespace]
 +-  └─ kubernetes:apps/v1:Deployment  deployment           replace     [diff: ~metadata]

Resources:
    ~ 1 to update
    +-1 to replace
    2 changes. 1 unchanged

```

The resultant stack state:
```json
            {
                "urn": "urn:pulumi:dev::issue-2486-yaml::pulumi:providers:kubernetes::k8s",
                "custom": true,
                "id": "78fe6e28-5f2e-4823-af95-df9021ce46f9",
                "type": "pulumi:providers:kubernetes",
                "inputs": {
                    "cluster": "docker-desktop",
                    "context": "docker-desktop",
                    "namespace": "default"
                },
                "outputs": {
                    "cluster": "docker-desktop",
                    "context": "docker-desktop",
                    "namespace": "default"
                },
                "parent": "urn:pulumi:dev::issue-2486-yaml::pulumi:pulumi:Stack::issue-2486-yaml-dev",
                "created": "2023-10-06T00:06:46.065029Z",
                "modified": "2023-10-06T00:06:46.065029Z"
            },
```

### Related issues (optional)

<!--Refer to related PRs or issues: #1234, or 'Fixes #1234' or 'Closes
#1234'.
Or link to full URLs to issues or pull requests in other GitHub
repositories. -->
EronWright added a commit that referenced this pull request Oct 20, 2023
<!--Thanks for your contribution. See [CONTRIBUTING](CONTRIBUTING.md)
    for Pulumi's contribution guidelines.

    Help us merge your changes more quickly by adding more details such
    as labels, milestones, and reviewers.-->


### Proposed changes

This is a series of commits to fix a p1 and to improve the import of
Helm Releases. The regression occurred because `Read` attempted to use
the provider-generated inputs to compute a checksum, and returned an
error if it couldn't, and this caused the `pulumi import` tool to fail
in cases where the inputs aren't guessable. The fix is to eat the
problem during `Read`.

While implementing the fix, it became apparent that the templating code
for the `Release` resource should be decoupled from the `Chart`
resource, mainly to improve the consistency of how chart names are
handled.

Specific changes:
- suppress error in computing inputs during `Read`.
- decouple the templating code.
- simplify the chart linting code.
- use a timeout that is consistent with the Delete op.
- new tests for the import variants.

<!--Give us a brief description of what you've done and what it solves.
-->
Closes #2596

### Related issues (optional)

<!--Refer to related PRs or issues: #1234, or 'Fixes #1234' or 'Closes
#1234'.
Or link to full URLs to issues or pull requests in other GitHub
repositories. -->

---------

Co-authored-by: Ramon Quitales <ramon@pulumi.com>
EronWright added a commit that referenced this pull request Oct 20, 2023
<!--Thanks for your contribution. See [CONTRIBUTING](CONTRIBUTING.md)
    for Pulumi's contribution guidelines.

    Help us merge your changes more quickly by adding more details such
    as labels, milestones, and reviewers.-->

### Proposed changes
This PR enhances the `Release` resource to search harder for a matching
chart when importing a release. When Helm installs a chart, it doesn't
record any information about the chart location, simply its name. Pulumi
attempts to locate a chart:
1. (existing) by looking for an expanded chart directory (e.g. `nginx/`)
in the program directory.
2. (new) by looking for a chart archive in the program directory, with
or without the version info (e.g. `nginx-15.3.4.tgz`).
3. (new) by looking in the local Helm repositories for a chart, matching
the name and version.

### Related issues (optional)

<!--Refer to related PRs or issues: #1234, or 'Fixes #1234' or 'Closes
#1234'.
Or link to full URLs to issues or pull requests in other GitHub
repositories. -->
EronWright added a commit that referenced this pull request Nov 8, 2023
…2653)

<!--Thanks for your contribution. See [CONTRIBUTING](CONTRIBUTING.md)
    for Pulumi's contribution guidelines.

    Help us merge your changes more quickly by adding more details such
    as labels, milestones, and reviewers.-->

### Proposed changes

This PR passes kubeVersion and apiVersions info from the server to Helm
to fix a regression that occurred in
#2568.

### Related issues (optional)

<!--Refer to related PRs or issues: #1234, or 'Fixes #1234' or 'Closes
#1234'.
Or link to full URLs to issues or pull requests in other GitHub
repositories. -->
Fixes: #2631
EronWright added a commit that referenced this pull request Nov 15, 2023
<!--Thanks for your contribution. See [CONTRIBUTING](CONTRIBUTING.md)
    for Pulumi's contribution guidelines.

    Help us merge your changes more quickly by adding more details such
    as labels, milestones, and reviewers.-->

### Proposed changes

<!--Give us a brief description of what you've done and what it solves.
-->
Closes #2644 

This PR fixes support for OCI charts on Windows, by making the code be
more consistent with Helm (see
[code](https://github.com/helm/helm/blob/main/pkg/action/install.go#L724)).
I believe the error comes from the call to `os.Stat` (see Golang
implementation which is based on CreateFile,
[here](https://go.dev/src/os/stat_windows.go)).

### Related issues (optional)

<!--Refer to related PRs or issues: #1234, or 'Fixes #1234' or 'Closes
#1234'.
Or link to full URLs to issues or pull requests in other GitHub
repositories. -->
EronWright added a commit that referenced this pull request Nov 27, 2023
<!--Thanks for your contribution. See [CONTRIBUTING](CONTRIBUTING.md)
    for Pulumi's contribution guidelines.

    Help us merge your changes more quickly by adding more details such
    as labels, milestones, and reviewers.-->

### Proposed changes

<!--Give us a brief description of what you've done and what it solves.
-->
This PR stabilizes Helm upgrades **by abandoning the use of checksums**
(which was added in v4.5.0, see
[PR](#2568)), while
allowing for local chart change detection via the chart's version
number. That is, the user would be expected to touch the chart's version
to compel Pulumi to roll out the change.

Implementation-wise, this is accomplished by resolving the `version`
property during `Check`. The checked input reflects the goal version,
and if the goal has changed, then `Diff` detects this in the natural way
and effects an upgrade. `Check` no longer uses `helm template` to render
the chart, it simply resolves the chart version.

The diff logic is improved here to use a three-way merge, to be able to
detect drift in the actual Helm release.

The refresh logic is improved to not mutate inputs (as was done in the
past to help with drift detection).

### Related issues (optional)

Closes #2649

<!--Refer to related PRs or issues: #1234, or 'Fixes #1234' or 'Closes
#1234'.
Or link to full URLs to issues or pull requests in other GitHub
repositories. -->
EronWright added a commit that referenced this pull request Nov 28, 2023
… resource" (#2677)

<!--Thanks for your contribution. See [CONTRIBUTING](CONTRIBUTING.md)
    for Pulumi's contribution guidelines.

    Help us merge your changes more quickly by adding more details such
    as labels, milestones, and reviewers.-->

### Proposed changes

<!--Give us a brief description of what you've done and what it solves.
-->

This PR fixes an intermittent problem that resembles:
```
 kubernetes:helm.sh/v3:Release (mongodb):
    error: 1 error occurred:
    	* Helm release "mongodb/mongodb-456643ba" failed to initialize completely. Use Helm CLI to investigate.: failed to become available within allocated timeout. Error: 
          Helm Release mongodb/mongodb-456643ba: release mongodb-456643ba failed, and has been rolled back due to atomic being set: 
          failed to create resource: the server could not find the requested resource
```

The problem was that a Go struct (containing a client-go rest config)
was being shared and mutated by numerous independent routines. The
solution was to copy the struct.

### Related issues (optional)

<!--Refer to related PRs or issues: #1234, or 'Fixes #1234' or 'Closes
#1234'.
Or link to full URLs to issues or pull requests in other GitHub
repositories. -->

Closes #2481
EronWright added a commit that referenced this pull request Jan 27, 2024
…2771)

<!--Thanks for your contribution. See [CONTRIBUTING](CONTRIBUTING.md)
    for Pulumi's contribution guidelines.

    Help us merge your changes more quickly by adding more details such
    as labels, milestones, and reviewers.-->

### Proposed changes

<!--Give us a brief description of what you've done and what it solves.
-->

This PR refactors the kubeconfig loading code to be more consistent
between `DiffConfig` and `Configure`. Previously the `DiffConfig` method
did not support file-based kubeconfigs, and would throw a spurious
parser error.

`DiffConfig` loads the kubeconfig to be able to detect cluster
replacement, by comparing the active cluster info. Unlike `Configure`,
it doesn't have support for ambient kubeconfigs. When an ambient config
is in use, or the config is invalid (e.g. the `context` or `cluster`
properties refer to a non-existent entry), then the replacement logic is
skipped.

This PR also fixes a panic in `DiffConfig` that would occur if `cluster`
or `context` is a computed value; the provider will conservatively
suggest replacement as it does when `kubeconfig` is a computed value.

### Testing
New test cases were added for cluster change detection.

New tests were added for the parsing code that was consolidated into
`utils.go`. The tests now cover file-, string-, and object-based
resource property values for `kubeconfig`.

### Related issues (optional)

<!--Refer to related PRs or issues: #1234, or 'Fixes #1234' or 'Closes
#1234'.
Or link to full URLs to issues or pull requests in other GitHub
repositories. -->
Closes: #2663 
Related: #1032
EronWright added a commit that referenced this pull request Feb 1, 2024
<!--Thanks for your contribution. See [CONTRIBUTING](CONTRIBUTING.md)
    for Pulumi's contribution guidelines.

    Help us merge your changes more quickly by adding more details such
    as labels, milestones, and reviewers.-->

### Proposed changes

<!--Give us a brief description of what you've done and what it solves.
-->

This PR implements unit tests for the await logic, i.e. the flow of
hitting the API server (with retry), then invoking the registered
awaiter to poll for success, then refreshing the live object.

### Related issues (optional)

<!--Refer to related PRs or issues: #1234, or 'Fixes #1234' or 'Closes
#1234'.
Or link to full URLs to issues or pull requests in other GitHub
repositories. -->

Closes #2791
EronWright added a commit that referenced this pull request Feb 2, 2024
<!--Thanks for your contribution. See [CONTRIBUTING](CONTRIBUTING.md)
    for Pulumi's contribution guidelines.

    Help us merge your changes more quickly by adding more details such
    as labels, milestones, and reviewers.-->

### Proposed changes

This PR clears the resource status after the awaiter completes, to
ensure that the status pertaining to a replacement resource (which would
have the same URN) isn't stale.

### Related issues (optional)

<!--Refer to related PRs or issues: #1234, or 'Fixes #1234' or 'Closes
#1234'.
Or link to full URLs to issues or pull requests in other GitHub
repositories. -->
Closes #2761
EronWright added a commit that referenced this pull request Feb 2, 2024
<!--Thanks for your contribution. See [CONTRIBUTING](CONTRIBUTING.md)
    for Pulumi's contribution guidelines.

    Help us merge your changes more quickly by adding more details such
    as labels, milestones, and reviewers.-->

### Proposed changes

<!--Give us a brief description of what you've done and what it solves.
-->

This PR changes the provider's await logic to get the object name from
the output properties rather than the input properties, since the inputs
may or may not contain an object name, to prepare to support
`generateName` field (see
#2539). Note that
auto-naming populates the inputs, whereas generateName doesn't.

The awaiters continue to look to the inputs (not the live object) for
the `skipAwait` and `timeout` annotations.

### Related issues (optional)

<!--Refer to related PRs or issues: #1234, or 'Fixes #1234' or 'Closes
#1234'.
Or link to full URLs to issues or pull requests in other GitHub
repositories. -->

Related: #2539
EronWright added a commit that referenced this pull request Feb 26, 2024
<!--Thanks for your contribution. See [CONTRIBUTING](CONTRIBUTING.md)
    for Pulumi's contribution guidelines.

    Help us merge your changes more quickly by adding more details such
    as labels, milestones, and reviewers.-->

### Proposed changes

<!--Give us a brief description of what you've done and what it solves.
-->

Skips the normalization step in the presence of computed inputs. 

Note: previously when `clients.Normalize` was called with a `Secret`, it
would panic. If called with a non-secret, an internal error would be
masked and the original object would be used.

### Related issues (optional)

<!--Refer to related PRs or issues: #1234, or 'Fixes #1234' or 'Closes
#1234'.
Or link to full URLs to issues or pull requests in other GitHub
repositories. -->
Closes #2845
EronWright added a commit that referenced this pull request Feb 26, 2024
<!--Thanks for your contribution. See [CONTRIBUTING](CONTRIBUTING.md)
    for Pulumi's contribution guidelines.

    Help us merge your changes more quickly by adding more details such
    as labels, milestones, and reviewers.-->

### Proposed changes

<!--Give us a brief description of what you've done and what it solves.
-->

### Related issues (optional)

<!--Refer to related PRs or issues: #1234, or 'Fixes #1234' or 'Closes
#1234'.
Or link to full URLs to issues or pull requests in other GitHub
repositories. -->
EronWright added a commit that referenced this pull request Mar 8, 2024
<!--Thanks for your contribution. See [CONTRIBUTING](CONTRIBUTING.md)
    for Pulumi's contribution guidelines.

    Help us merge your changes more quickly by adding more details such
    as labels, milestones, and reviewers.-->

### Proposed changes

<!--Give us a brief description of what you've done and what it solves.
-->

A follow-up to #2863 to
upgrade to pu/pu v3.109.0 across the board.

### Related issues (optional)

<!--Refer to related PRs or issues: #1234, or 'Fixes #1234' or 'Closes
#1234'.
Or link to full URLs to issues or pull requests in other GitHub
repositories. -->
EronWright added a commit that referenced this pull request Mar 12, 2024
<!--Thanks for your contribution. See [CONTRIBUTING](CONTRIBUTING.md)
    for Pulumi's contribution guidelines.

    Help us merge your changes more quickly by adding more details such
    as labels, milestones, and reviewers.-->

### Proposed changes

<!--Give us a brief description of what you've done and what it solves.
-->

This PR teaches `ConfigGroup` to detect whether a given file path is a
glob pattern, to make the handling of non-existent files be consistent
w.r.t `ConfigFile`. In other words, `*.yaml` MAY match a file whereas
`manifest.yaml` MUST match a file.

The detection code looks for special characters '*', '?', and '[' and
respects the escape syntax. Intended to be consistent with:
[https://pkg.go.dev/path/filepath#Match](https://pkg.go.dev/path/filepath#Match)

An alternative to doing pattern detection would be:
1. to expose a `glob` property to toggle globbing, or 
2. a `patterns` property alongside the `files` property for patterns and
non-patterns respectively

### Related issues (optional)

<!--Refer to related PRs or issues: #1234, or 'Fixes #1234' or 'Closes
#1234'.
Or link to full URLs to issues or pull requests in other GitHub
repositories. -->
Closes #2871
rquitales pushed a commit that referenced this pull request Mar 13, 2024
<!--Thanks for your contribution. See [CONTRIBUTING](CONTRIBUTING.md)
    for Pulumi's contribution guidelines.

    Help us merge your changes more quickly by adding more details such
    as labels, milestones, and reviewers.-->

<!--Give us a brief description of what you've done and what it solves.
-->

A follow-up to #2863 to
upgrade to pu/pu v3.109.0 across the board.

<!--Refer to related PRs or issues: #1234, or 'Fixes #1234' or 'Closes
Or link to full URLs to issues or pull requests in other GitHub
repositories. -->

(cherry picked from commit 7246ed3)
EronWright added a commit that referenced this pull request Mar 19, 2024
<!--Thanks for your contribution. See [CONTRIBUTING](CONTRIBUTING.md)
    for Pulumi's contribution guidelines.

    Help us merge your changes more quickly by adding more details such
    as labels, milestones, and reviewers.-->

### Proposed changes

<!--Give us a brief description of what you've done and what it solves.
-->

This PR fixes a couple of related problems with "ambiguous kinds":
1. For kinds with clashing names (e.g. `Role`), be sure to check the
apiversion before using built-in information or dynamic discovery.
2. For kinds with casing problems, don't mask the problem; show the API
server error.

Note that kubectl has the following behavior w.r.t (2):

```yaml
apiVersion: awx.ansible.com/v1beta1
kind: awx
metadata:
  name: my-awx
  namespace: awx
```

```
❯ kubectl apply -f manifest.yaml --server-side=false
The awx "my-awx" is invalid: kind: Invalid value: "awx": must be AWX
❯ kubectl apply -f manifest.yaml --server-side=true
Error from server (BadRequest): invalid object type: awx.ansible.com/v1beta1, Kind=awx
```

An explanation of the technical approach: the `kinds.Kind` type is used
in the codebase to represent a well-known kind, i.e. known at code
generation time. To prepare this PR, I audited the locations where
`Kind` is used, and ensured that it wasn't being used for arbitrary
kinds. Where necessary, the use of `Kind` was conditioned on the
`apiVersion` being one of the well-known values.

### Related issues (optional)

<!--Refer to related PRs or issues: #1234, or 'Fixes #1234' or 'Closes
#1234'.
Or link to full URLs to issues or pull requests in other GitHub
repositories. -->

Closes #2865
Closes #2143
EronWright added a commit that referenced this pull request Mar 19, 2024
<!--Thanks for your contribution. See [CONTRIBUTING](CONTRIBUTING.md)
    for Pulumi's contribution guidelines.

    Help us merge your changes more quickly by adding more details such
    as labels, milestones, and reviewers.-->

### Proposed changes

This PR doesn't make any substantive changes to the provider, it breaks
apart the parsing-and-registration code into two independent functions,
in anticipation of applying component-specific sorting strategies.

Specifics:
- split the logic into `Parse` and `Register`
- split the test code accordingly
- enriches the registration data that is collected by the mock resource
monitor

### Related issues (optional)

<!--Refer to related PRs or issues: #1234, or 'Fixes #1234' or 'Closes
#1234'.
Or link to full URLs to issues or pull requests in other GitHub
repositories. -->
EronWright added a commit that referenced this pull request Mar 21, 2024
<!--Thanks for your contribution. See [CONTRIBUTING](CONTRIBUTING.md)
    for Pulumi's contribution guidelines.

    Help us merge your changes more quickly by adding more details such
    as labels, milestones, and reviewers.-->

### Proposed changes

<!--Give us a brief description of what you've done and what it solves.
-->

This PR adds support for resource ordering within a `ConfigGroup` or
`ConfigFile`. Two approaches are supported (and work in combination):
1. implicit dependencies: the provider uses heuristics to install CRDs
and namespaces first.
2. explicit dependencies: the provider understands the
`config.kubernetes.io/depends-on` annotation to explicitly declare a
dependency on a given resource.

The implementation is based on
[kubernetes-sigs/cli-utils](https://github.com/kubernetes-sigs/cli-utils)
and its support for resource ordering
([documentation](https://github.com/kubernetes-sigs/cli-utils?tab=readme-ov-file#resource-ordering)).

To be clear, ordering _across_ `ConfigGroup` resources is supported
already, simply using the `dependsOn` option. This PR adds a more
granular ordering _within_ the group.

### Testing
New test cases were added to verify the new behavior. Many tests rely on
a common manifest file, and it is updated to include a CRD and a
namespace.

Manual testing was performed with the following well-known manifests:
1. knative-serving-core
([ref](https://github.com/knative/serving/releases/download/knative-v1.13.1/serving-core.yaml))
2. cert-manager
([ref](https://github.com/cert-manager/cert-manager/releases/download/v1.14.4/cert-manager.yaml))

### Example
Here's an example that installs cert-manager then provisions a
certificate issuer and a TLS certificate. An explicit dependency is
drawn between the `Certificate` and `Issuer`.

```yaml
name: issue-2881-cert-manager
runtime: yaml
description: Installs cert-manager.  See https://cert-manager.io/docs/installation/kubectl/ for details.
variables: {}
resources:
  install:
    type: kubernetes:yaml/v2:ConfigGroup
    properties:
      files:
      - https://github.com/cert-manager/cert-manager/releases/download/v1.14.4/cert-manager.yaml
  test:
    type: kubernetes:yaml/v2:ConfigGroup
    options:
      dependsOn:
      - ${install}
    properties:
      yaml: |
        apiVersion: v1
        kind: Namespace
        metadata:
          name: cert-manager-test
        ---
        apiVersion: cert-manager.io/v1
        kind: Issuer
        metadata:
          name: test-selfsigned
          namespace: cert-manager-test
        spec:
          selfSigned: {}
        ---
        apiVersion: cert-manager.io/v1
        kind: Certificate
        metadata:
          name: selfsigned-cert
          namespace: cert-manager-test
          annotations:
            config.kubernetes.io/depends-on: cert-manager.io/namespaces/cert-manager-test/Issuer/test-selfsigned
        spec:
          dnsNames:
            - example.com
          secretName: selfsigned-cert-tls
          issuerRef:
            name: test-selfsigned
```

Within the stack state, one sees dependencies, e.g. on the `Certificate`
resource.
```json
{
    "urn": "urn:pulumi:dev::issue-2881-cert-manager::kubernetes:yaml/v2:ConfigGroup$kubernetes:cert-manager.io/v1:Certificate::test-cert-manager-test/selfsigned-cert",
    "id": "cert-manager-test/selfsigned-cert",
    "type": "kubernetes:cert-manager.io/v1:Certificate",
    "dependencies": [
        "urn:pulumi:dev::issue-2881-cert-manager::kubernetes:yaml/v2:ConfigGroup$kubernetes:cert-manager.io/v1:Issuer::test-cert-manager-test/test-selfsigned",
        "urn:pulumi:dev::issue-2881-cert-manager::kubernetes:yaml/v2:ConfigGroup$kubernetes:core/v1:Namespace::test-cert-manager-test"
    ]
}
```

### Related issues (optional)

<!--Refer to related PRs or issues: #1234, or 'Fixes #1234' or 'Closes
#1234'.
Or link to full URLs to issues or pull requests in other GitHub
repositories. -->

Closes #2881
EronWright added a commit that referenced this pull request Mar 21, 2024
<!--Thanks for your contribution. See [CONTRIBUTING](CONTRIBUTING.md)
    for Pulumi's contribution guidelines.

    Help us merge your changes more quickly by adding more details such
    as labels, milestones, and reviewers.-->

### Proposed changes

This PR strengthens the normalization of the parsed Kubernetes objects
to better interoperate with #2881.
Specifically:
1. Applies the default namespace as necessary on each object, so that
they may be reliably targeted by the `depends-on` resource.
2. Stabilizes the resource id (e.g. `default/my-map` versus `my-map`).
3. Validates that the objects are well-formed more eagerly than during
`Register`.

For example, given the below manifest and assuming that the default
namespace is `default`, we would expect a `DependsOn` option from
`Certificate` to `Issuer`. Observe that `namespace` isn't explicitly set
on the issuer.

```yaml
name: issue-2870-cert-manager
runtime: yaml
resources:
  example:
    type: kubernetes:yaml/v2:ConfigGroup
    properties:
      yaml: |
        apiVersion: cert-manager.io/v1
        kind: Issuer
        metadata:
          name: test-selfsigned
        spec:
          selfSigned: {}
        ---
        apiVersion: cert-manager.io/v1
        kind: Certificate
        metadata:
          name: selfsigned-cert
          annotations:
            config.kubernetes.io/depends-on: cert-manager.io/namespaces/default/Issuer/test-selfsigned
        spec:
          dnsNames:
            - example.com
          secretName: selfsigned-cert-tls
          issuerRef:
            name: test-selfsigned
```

To apply the default namespace correctly, one must know whether a given
kind is namespace-scoped. The provider naturally uses the discovery
client, and also looks for a matching CRD amongst the parsed objects
(since they're not yet installed).

### Testing
New test cases were added for `Normalize`, and some test cases were
moved from `Register` because the validation is performed more eagerly.

New sub-tests were added for `IsNamespacedKind` to cover the local CRD
enhancement.

### Related issues (optional)

<!--Refer to related PRs or issues: #1234, or 'Fixes #1234' or 'Closes
#1234'.
Or link to full URLs to issues or pull requests in other GitHub
repositories. -->

Closes #2870
EronWright added a commit that referenced this pull request Mar 22, 2024
<!--Thanks for your contribution. See [CONTRIBUTING](CONTRIBUTING.md)
    for Pulumi's contribution guidelines.

    Help us merge your changes more quickly by adding more details such
    as labels, milestones, and reviewers.-->

### Proposed changes

<!--Give us a brief description of what you've done and what it solves.
-->
This PR changes the prefix character that is used, as per this
discussion:
https://pulumi.slack.com/archives/C8R654Y6S/p1711035557620359

Tested with a few well-known manifests and seems to be a good
improvement on readability.

```plain
     pulumi:pulumi:Stack                                                              issue-2881-cert-manager-dev                                            4 warn
     ├─ kubernetes:yaml/v2:ConfigGroup                                                install                                                                
 +   │  ├─ kubernetes:core/v1:Namespace                                               install:cert-manager                                        create     
 +   │  ├─ kubernetes:rbac.authorization.k8s.io/v1:ClusterRole                        install:cert-manager-cluster-view                           create     
 +   │  ├─ kubernetes:rbac.authorization.k8s.io/v1:ClusterRole                        install:cert-manager-controller-certificates                create     
 +   │  ├─ kubernetes:rbac.authorization.k8s.io/v1:ClusterRole                        install:cert-manager-edit                                   create     
 +   │  ├─ kubernetes:core/v1:ServiceAccount                                          install:cert-manager/cert-manager-webhook                   create     
 +   │  ├─ kubernetes:core/v1:ServiceAccount                                          install:cert-manager/cert-manager                           create     
 +   │  ├─ kubernetes:rbac.authorization.k8s.io/v1:ClusterRole                        install:cert-manager-view                                   create     
 +   │  ├─ kubernetes:rbac.authorization.k8s.io/v1:ClusterRole                        install:cert-manager-controller-issuers                     create     
 +   │  ├─ kubernetes:rbac.authorization.k8s.io/v1:ClusterRole                        install:cert-manager-controller-clusterissuers              create     
 +   │  ├─ kubernetes:core/v1:ServiceAccount                                          install:cert-manager/cert-manager-cainjector                create     
 +   │  ├─ kubernetes:rbac.authorization.k8s.io/v1:ClusterRole                        install:cert-manager-controller-ingress-shim                create     
 +   │  ├─ kubernetes:apiextensions.k8s.io/v1:CustomResourceDefinition                install:certificaterequests.cert-manager.io                 create     
 +   │  ├─ kubernetes:rbac.authorization.k8s.io/v1:ClusterRoleBinding                 install:cert-manager-controller-certificates                create     
 +   │  ├─ kubernetes:rbac.authorization.k8s.io/v1:ClusterRole                        install:cert-manager-cainjector                             create     
 +   │  ├─ kubernetes:core/v1:Service                                                 install:cert-manager/cert-manager                           create     
 +   │  ├─ kubernetes:rbac.authorization.k8s.io/v1:Role                               install:kube-system/cert-manager-cainjector:leaderelection  create     
 +   │  ├─ kubernetes:rbac.authorization.k8s.io/v1:RoleBinding                        install:cert-manager/cert-manager-webhook:dynamic-serving   create     
 +   │  ├─ kubernetes:rbac.authorization.k8s.io/v1:Role                               install:cert-manager/cert-manager-webhook:dynamic-serving   create     
 +   │  ├─ kubernetes:rbac.authorization.k8s.io/v1:ClusterRole                        install:cert-manager-controller-certificatesigningrequests  create     
 +   │  ├─ kubernetes:rbac.authorization.k8s.io/v1:ClusterRoleBinding                 install:cert-manager-controller-certificatesigningrequests  create     
 +   │  ├─ kubernetes:rbac.authorization.k8s.io/v1:Role                               install:kube-system/cert-manager:leaderelection             create     
 +   │  ├─ kubernetes:rbac.authorization.k8s.io/v1:ClusterRole                        install:cert-manager-controller-approve:cert-manager-io     create     
```

### Related issues (optional)

<!--Refer to related PRs or issues: #1234, or 'Fixes #1234' or 'Closes
#1234'.
Or link to full URLs to issues or pull requests in other GitHub
repositories. -->
EronWright added a commit that referenced this pull request Mar 27, 2024
<!--Thanks for your contribution. See [CONTRIBUTING](CONTRIBUTING.md)
    for Pulumi's contribution guidelines.

    Help us merge your changes more quickly by adding more details such
    as labels, milestones, and reviewers.-->

### Proposed changes

<!--Give us a brief description of what you've done and what it solves.
-->
The yaml/v2 package eagerly resolves kinds to apply a default namespace.
This PR addresses a problem with the use case
where a kind is installed by one `ConfigGroup` and then used by another.
In preview mode, the kind cannot be found by the latter group because
the expected side-effect (i.e. installation of a CRD) doesn't occur.

The solution to the issue is to maintain a cache in the provider of new
CRDs. When the provider executes `Check` on a `CustomResourceDefinition`
resource, it adds the CRD to the cache. Later, when a component resource
must resolve a given kind, it checks the cache. In this way, the cache
compensates for the lack of side-effects (i.e. API server calls) that
would normally allow the kind to be resolved. Overall ordering is
established using `DependsOn`.

It is reasonable to populate the cache during `Check` because a)`Check`
produces the "planned" state that is needed later without actuating it,
and b) `Update` is called conditionally and thus isn't a reliable
alternative.

### Implementation Details
The provider has three overlapping modes of operation - preview-mode,
`clusterUnreachable` and `yamlRenderMode` - that affect the
initialization and use of `clientSet`. Previously when
`clusterUnreachable` is true then the `clientSet` is left null. Now, we
new-up the `clientSet` itself but leave its various fields null. This
change makes it possible to use the CRD cache in all modes, as was
necessary to support `yamlRenderMode`.

### Testing
A new integration test is added called `yamlv2` that exercises this
scenario.

Manual testing of "cluster unreachable mode" was done by misconfiguring
my local environment (to have an invalid kube context). Tested in
combination with "yaml rendering mode" and found that the latter works
as expected even when the cluster is unreachable.

### Related issues (optional)

<!--Refer to related PRs or issues: #1234, or 'Fixes #1234' or 'Closes
#1234'.
Or link to full URLs to issues or pull requests in other GitHub
repositories. -->
EronWright added a commit that referenced this pull request Mar 28, 2024
<!--Thanks for your contribution. See [CONTRIBUTING](CONTRIBUTING.md)
    for Pulumi's contribution guidelines.

    Help us merge your changes more quickly by adding more details such
    as labels, milestones, and reviewers.-->

### Proposed changes

<!--Give us a brief description of what you've done and what it solves.
-->
Updated the codedocs for new ConfigGroup and ConfigFile (v2) resources.
A working example is also provided for YAML and Java.

### Related issues (optional)

<!--Refer to related PRs or issues: #1234, or 'Fixes #1234' or 'Closes
#1234'.
Or link to full URLs to issues or pull requests in other GitHub
repositories. -->

Closes #2868
EronWright added a commit that referenced this pull request Apr 12, 2024
<!--Thanks for your contribution. See [CONTRIBUTING](CONTRIBUTING.md)
    for Pulumi's contribution guidelines.

    Help us merge your changes more quickly by adding more details such
    as labels, milestones, and reviewers.-->

### Proposed changes

<!--Give us a brief description of what you've done and what it solves.
-->

### Related issues (optional)

<!--Refer to related PRs or issues: #1234, or 'Fixes #1234' or 'Closes
#1234'.
Or link to full URLs to issues or pull requests in other GitHub
repositories. -->
EronWright added a commit that referenced this pull request Apr 17, 2024
…2957)

<!--Thanks for your contribution. See [CONTRIBUTING](CONTRIBUTING.md)
    for Pulumi's contribution guidelines.

    Help us merge your changes more quickly by adding more details such
    as labels, milestones, and reviewers.-->

### Proposed changes

This PR fixes the "panic" that occurs when an uninitialized provider is
used with the yaml/kustomize resources. In that situation, the invoke
calls aren't performed and the engine simply returns an uninitialized
result. This causes a problem in the callers because the methods on
`ImmutableArray` mustn't be used when the value is uninitialized
(`IsDefault` is true).

### Example
The example given in #2741 easily repros the issue. With this fix, the
behavior improves:

```
Diagnostics:
  kubernetes:yaml:ConfigFile (guestbook):
    warning: Required input properties have unknown values. Preview is incomplete.

Outputs:
    FrontendIp: output<string>
```

### Testing
Includes integration tests involving an uninitialized provider with a
`ConfigFile` or `Directory`.

### Related issues (optional)

<!--Refer to related PRs or issues: #1234, or 'Fixes #1234' or 'Closes
#1234'.
Or link to full URLs to issues or pull requests in other GitHub
repositories. -->

Closes #2741
EronWright added a commit that referenced this pull request May 15, 2024
<!--Thanks for your contribution. See [CONTRIBUTING](CONTRIBUTING.md)
    for Pulumi's contribution guidelines.

    Help us merge your changes more quickly by adding more details such
    as labels, milestones, and reviewers.-->

### Proposed changes

<!--Give us a brief description of what you've done and what it solves.
-->
This PR implements an MLC-based `Chart` resource as per [design
doc](https://docs.google.com/document/d/1_DZlsAyG4-3BxrAkJBj8R6wIVuzhAkxRDyq8k_Zcst4/edit?usp=sharing).

Notable improvements over v3:Chart:

- Input schema more closely resembles v3:Release.
- Performs templating in an online mode.
- More control over resource ordering via annotation:
`config.kubernetes.io/depends-on`
- Uses [Pulumi
Assets](https://www.pulumi.com/docs/concepts/assets-archives/) for
supplemental files (keyring, repository opts).
- Use assets as values files (`--values`) and as individual values
(`--set-file`).
- Use multiple values files.
- Support for post-rendering w/ arguments.
- OCI registry support.

Detailed changes:
- [pkg/helm] introduce a reusable Helm tool wrapper
- [pkg/gen] define `helm.sh/v4:Chart` resource plus
`v4:PostRenderer,v4:RepositoryOpts`
- [provider] initialize the Helm EnvSettings based on provider
configuration
- [provider/helmv4] implement Chart resource provider
- [provider/yamlv2] add `PreRegisterF` hook to be able to mutate child
resource options, specifically `RetainOnDelete`
- [provider/yamlv2] new gomega matcher: `HaveSkipAwaitAnnotation()`
- [tests/testdata] new 'reference' chart for testing purposes
- [misc] bugfix for kube client settings

Tests:
- New suite for Chart provider w/ coverage of all in-scope features
- Extended tests for provider Construct RPC to cover namespacing, kube
client settings, helm release settings

### Examples

See the examples in the API docs:

https://github.com/pulumi/pulumi-kubernetes/blob/47a6ae4fceb8339c49d4f13b5f765af798c0308b/provider/pkg/gen/examples/overlays/chartV4.md#example-usage

Local Chart:
```yaml
type: kubernetes:helm.sh/v4:Chart
properties:
  namespace: cert-manager
  chart: ./cert-manager
```

Repository Chart:
```yaml
# helm repo add bitnami https://charts.bitnami.com/bitnami
type: kubernetes:helm.sh/v4:Chart
properties:
  namespace: cert-manager
  chart: bitnami/cert-manager
  version: "1.1.0"
```

Remote Chart:
```yaml
type: kubernetes:helm.sh/v4:Chart
properties:
  namespace: cert-manager
  chart: cert-manager
  version: "1.1.0"
  repositoryOpts:
    repo: https://charts.bitnami.com/bitnami
```

OCI Chart:
```yaml
type: kubernetes:helm.sh/v4:Chart
properties:
  namespace: cert-manager
  chart: oci://registry-1.docker.io/bitnamicharts/cert-manager
  version: "1.1.0"
```

Custom Values:
```yaml
type: kubernetes:helm.sh/v4:Chart
properties:
  namespace: cert-manager
  chart: oci://registry-1.docker.io/bitnamicharts/cert-manager
  version: "1.1.0"
  values:
    installCRDs: false
    notes:
      fn::fileAsset: notes.txt
  valueYamlFiles:
  - fn::fileAsset: values.yaml
```

Chart Verification w/ Keyring:
```yaml
type: kubernetes:helm.sh/v4:Chart
properties:
  namespace: cert-manager
  chart: oci://registry-1.docker.io/eronwrightpulumi/cert-manager
  version: "1.1.0"
  verify: true
  keyring:
    fn::fileAsset: "public.pgp"
```

Post-Rendering:
```yaml
type: kubernetes:helm.sh/v4:Chart
properties:
  namespace: cert-manager
  chart: oci://registry-1.docker.io/bitnamicharts/cert-manager
  version: "1.1.0"
  postRenderer:
    command: ./kustomize
    args: []
```

### Related issues (optional)

<!--Refer to related PRs or issues: #1234, or 'Fixes #1234' or 'Closes
#1234'.
Or link to full URLs to issues or pull requests in other GitHub
repositories. -->

Fixes #2847
EronWright added a commit that referenced this pull request May 17, 2024
<!--Thanks for your contribution. See [CONTRIBUTING](CONTRIBUTING.md)
    for Pulumi's contribution guidelines.

    Help us merge your changes more quickly by adding more details such
    as labels, milestones, and reviewers.-->

### Proposed changes

<!--Give us a brief description of what you've done and what it solves.
-->

Introduces a new Pulumi annotation to set the [deletion propagation
policy](https://kubernetes.io/docs/tasks/administer-cluster/use-cascading-deletion/),
e.g. to support non-cascading delete on `StatefulSet` to preserve pods
during replacement (see
[walkthrough](https://kubernetes.io/docs/tutorials/stateful-application/basic-stateful-set/#non-cascading-delete)).

Note that the policy annotation must be set on the old resource before
deleting or replacing it; setting it on the replacement or on the live
object is ineffective.

### Related issues (optional)

<!--Refer to related PRs or issues: #1234, or 'Fixes #1234' or 'Closes
#1234'.
Or link to full URLs to issues or pull requests in other GitHub
repositories. -->

Closes #1831 

### Example

This example serves to show how the 'orphan' propagation policy allows
for non-disruptive replacement of
a StatefulSet, e.g. by touching the `volumeClaimTemplates`.

```yaml
name: issue-1831
runtime: yaml
description: A StatefulSet to demonstrate the `pulumi.com/deletionPropagationPolicy` annotation.
config:
  # disable SSA for this demonstration
  kubernetes:enableServerSideApply: false
resources:
  nginx:
    type: kubernetes:apps/v1:StatefulSet
    properties:
      metadata:
        name: nginx
        annotations:
          pulumi.com/deletionPropagationPolicy: "orphan"
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: nginx
        serviceName: nginx
        template:
          metadata:
            labels:
              app: nginx
          spec:
            containers:
            - image: nginx:1.19.9
              name: nginx
              ports:
              - containerPort: 80
                name: web
        volumeClaimTemplates:
        - metadata:
            name: nginx
          spec:
            accessModes:
            - ReadWriteOnce
            resources:
              requests:
                storage: 1Gi
```

Following the initial deployment, we have these objects:
```
❯ kubectl get statefulset,pod,pvc -ocustom-columns='KIND:.kind,NAME:.metadata.name,UID:.metadata.uid'
KIND                    NAME            UID
StatefulSet             nginx           b1aa144d-3f16-448e-8e15-02d2c2d4b61a
Pod                     nginx-0         c00d97cc-39d7-4a95-b839-0910f911dbca
PersistentVolumeClaim   nginx-nginx-0   2c624ff9-e856-4d2d-bfaf-527c6b770bc7
```

To provoke a replacement, we change the PVC template:
```
              requests:
-                storage: 1Gi
+                storage: 2Gi
```
Let's also increase the replicas:
```
      spec:
-        replicas: 1
+        replicas: 2
```

And deploy:
```
❯ pulumi up -f
Updating (dev)

     Type                               Name            Status            Info
     pulumi:pulumi:Stack                issue-1831-dev                    4 warnings; 2 messages
 +-  └─ kubernetes:apps/v1:StatefulSet  nginx           replaced (2s)     [diff: ~spec]

Resources:
    +-1 replaced
    1 unchanged
```

Looking again at the objects:
```
❯ kubectl get statefulset,pod,pvc -ocustom-columns='KIND:.kind,NAME:.metadata.name,UID:.metadata.uid'
KIND                    NAME            UID
StatefulSet             nginx           135d9142-460c-4f64-82a6-8ce23427f52b
Pod                     nginx-0         c00d97cc-39d7-4a95-b839-0910f911dbca
Pod                     nginx-1         8c80932f-7051-4fc7-baeb-00dae4b07b64
PersistentVolumeClaim   nginx-nginx-0   2c624ff9-e856-4d2d-bfaf-527c6b770bc7
PersistentVolumeClaim   nginx-nginx-1   e4b4fd18-28b2-454b-8c6b-9fa06435d3d6
```

We see the expected result: the StatefulSet was replaced, the existing
pod was adopted, and a new pod was added w/ a PVC.

In more detail, the StatefulSet controller uses the selector to identify
existing pods, then chooses to delete or adopt based on suitability.
Note the updated owner reference on `nginx-0`:
```yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx-0
  uid: c00d97cc-39d7-4a95-b839-0910f911dbca
  ownerReferences:
  - apiVersion: apps/v1
    blockOwnerDeletion: true
    controller: true
    kind: StatefulSet
    name: nginx
    uid: 135d9142-460c-4f64-82a6-8ce23427f52b
```

To demonstrate how the StatefulSet controller might choose to delete the
existing pod rather than adopting it, let's change the image rather than
the replicas:
```
            containers:
-            - image: nginx:1.19.9
+            - image: nginx:1.19.10
 
              requests:
-                storage: 2Gi
+                storage: 3Gi
```

We deploy again and see that all pods were replaced.
```
KIND                    NAME            UID
StatefulSet             nginx           ead53943-abc9-47c8-9393-326f845c7f42
Pod                     nginx-0         74752b8c-3979-478b-9be4-ff3ca1b0aa6f
Pod                     nginx-1         b6c2f0f6-f5ff-4e04-a1da-66966b8d697c
PersistentVolumeClaim   nginx-nginx-0   2c624ff9-e856-4d2d-bfaf-527c6b770bc7
PersistentVolumeClaim   nginx-nginx-1   e4b4fd18-28b2-454b-8c6b-9fa06435d3d6
```

Note that PVC `nginx-nginx-0` was not replaced and still has `storage:
1Gi`.
EronWright added a commit that referenced this pull request May 20, 2024
<!--Thanks for your contribution. See [CONTRIBUTING](CONTRIBUTING.md)
    for Pulumi's contribution guidelines.

    Help us merge your changes more quickly by adding more details such
    as labels, milestones, and reviewers.-->

### Proposed changes

<!--Give us a brief description of what you've done and what it solves.
-->

### Related issues (optional)

<!--Refer to related PRs or issues: #1234, or 'Fixes #1234' or 'Closes
#1234'.
Or link to full URLs to issues or pull requests in other GitHub
repositories. -->

Closes #2800
EronWright added a commit that referenced this pull request May 21, 2024
<!--Thanks for your contribution. See [CONTRIBUTING](CONTRIBUTING.md)
    for Pulumi's contribution guidelines.

    Help us merge your changes more quickly by adding more details such
    as labels, milestones, and reviewers.-->

### Proposed changes

<!--Give us a brief description of what you've done and what it solves.
-->

### Related issues (optional)

<!--Refer to related PRs or issues: #1234, or 'Fixes #1234' or 'Closes
#1234'.
Or link to full URLs to issues or pull requests in other GitHub
repositories. -->
EronWright added a commit that referenced this pull request May 24, 2024
<!--Thanks for your contribution. See [CONTRIBUTING](CONTRIBUTING.md)
    for Pulumi's contribution guidelines.

    Help us merge your changes more quickly by adding more details such
    as labels, milestones, and reviewers.-->

### Proposed changes

This PR updates the pulumi-java dependency from v0.8.0 to v0.12.0.

Notable changes:
- pulumi/pulumi-java#1356
- pulumi/pulumi-java#1361
- pulumi/pulumi-java#1228

### Related issues (optional)

<!--Refer to related PRs or issues: #1234, or 'Fixes #1234' or 'Closes
#1234'.
Or link to full URLs to issues or pull requests in other GitHub
repositories. -->
EronWright added a commit that referenced this pull request May 28, 2024
<!--Thanks for your contribution. See [CONTRIBUTING](CONTRIBUTING.md)
    for Pulumi's contribution guidelines.

    Help us merge your changes more quickly by adding more details such
    as labels, milestones, and reviewers.-->

### Proposed changes

<!--Give us a brief description of what you've done and what it solves.
-->
Implements `CustomResource` for Java SDK as an overlay, for parity with
other SDKs. An overlay is necessary for [this
reason](#2787 (comment)).

#### Features
Supports two usage modes. Note that each SDK is slightly different in
which mode(s) it supports.
- **untyped**, where you use `CustomResource` directly and set arbitrary
fields on the object.
- **typed**, where you subclass `CustomResource` to create a
strongly-typed wrapper representing a CRD.

A "Patch" variant is also provided.

Provides a "getter" method in both untyped and typed mode. Note that the
patch variant doesn't have a getter in most SDKs.

#### Summary of Changes
- new example: `examples/java/customresource`
- new resource: `apiextensions.CustomResource`
- new resource: `apiextensions.CustomResourcePatch`
- new dependency: `net.bytebuddy:byte-buddy:1.14.15`
- new dependency:`com.google.guava:guava:32.1.2-jre` (used by core
already)

TODOs:

- [x] Prerequisite: Pulumi Java 0.12
(pulumi/pulumi-java#1361)
- [x] `Get` method (untyped and typed)
- [x] Patch variant
- [x] Integration test or in-tree example

### Related issues (optional)

<!--Refer to related PRs or issues: #1234, or 'Fixes #1234' or 'Closes
#1234'.
Or link to full URLs to issues or pull requests in other GitHub
repositories. -->
Closes #2787 

### API

- `CustomResource` - to be used directly or subclassed to expose typed
output properties
- `CustomResourceArgs` - the final class to be used directly in the
untyped use-case
- `CustomResourceArgsBase` - the abstract base class for custom resource
args, to expose typed input properties
- `CustomResourceArgsBase.Builder<T,B>` - the base class for your custom
args builder
- `CustomResourcePatch` - to be used directly or subclassed to expose
typed output properties
- `CustomResourcePatchArgs` - the final class to be used directly in the
untyped use-case
- `CustomResourcePatchArgsBase` - the abstract base class for custom
resource args, to expose typed input properties
- `CustomResourcePatchArgsBase.Builder<T,B>` - the base class for your
custom args builder

### Implementation Details

#### Working with Untyped Inputs
The core Pulumi Java SDK has no support for dynamic inputs; it relies
exclusively on reflection of the supplied `InputArgs` subclass (see:
[`InputArgs::toMapAsync`](https://github.com/pulumi/pulumi-java/blob/f887fbc869974ae7d9049cb4a5b62f51b1151dcb/sdk/java/pulumi/src/main/java/com/pulumi/resources/InputArgs.java#L63)).
To support the "untyped" mode, this implementation codegens a class at
runtime using bytebuddy.

#### Builder Inheritance
The Java SDK leans on the fluent builder pattern, and there are special
challenges in designing a builder that is amenable to inheritance. This
implementation uses generics as seen
[here](https://egalluzzo.blogspot.com/2010/06/using-inheritance-with-fluent.html).

## Example

Here's an example program to deploy two [cert-manager
issuers](https://cert-manager.io/docs/concepts/issuer/).
- `issuer1` is untyped, and calls `otherFields(...)` on the builder to
set the `spec`.
- `issuer2` is typed, calls `spec(...)` on a subclassed builder to set
the `spec`, and uses the typed `spec` output. Note that the `apiVersion`
and `kind` are set automatically.

The code seen in `Inputs` and `Outputs` section would, in practice, be
generated by pulumi-java-gen based on a schema file.

The untyped and typed getter variants are also demonstrated.

```java
package myproject;

import java.util.Map;
import java.util.Objects;
import java.util.Optional;

import javax.annotation.Nullable;

import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.core.annotations.CustomType;
import com.pulumi.core.annotations.Export;
import com.pulumi.core.annotations.Import;
import com.pulumi.kubernetes.apiextensions.CustomResource;
import com.pulumi.kubernetes.apiextensions.CustomResourceArgs;
import com.pulumi.kubernetes.apiextensions.CustomResourceArgsBase;
import com.pulumi.kubernetes.meta.v1.inputs.ObjectMetaArgs;

public class App {
    public static void main(String[] args) {
        Pulumi.run(ctx -> {
            var issuer1 = new CustomResource("issuer1", CustomResourceArgs.builder()
                    .apiVersion("cert-manager.io/v1")
                    .kind("Issuer")
                    .metadata(ObjectMetaArgs.builder().build())
                    .otherFields(Map.of("spec", Map.of(
                            "selfSigned", Map.of())))
                    .build());
            ctx.export("issuer1_name", issuer1.metadata().applyValue(s -> s.name()));

            var get1 = CustomResource.get("get1", "cert-manager.io/v1", "Issuer", issuer1.id(), null);
                
            var issuer2 = new Issuer("issuer2", IssuerArgs.builder()
                    .metadata(ObjectMetaArgs.builder().build())
                    .spec(Inputs.IssuerSpecArgs.builder()
                            .selfSigned(Inputs.SelfSignedArgs.builder().build())
                            .build())
                    .build());

            ctx.export("issuer2_name", issuer2.metadata().applyValue(s -> s.name()));
            ctx.export("issuer2_selfsigned", issuer2.spec().applyValue(s -> s.selfSigned().isPresent()));

            var get2 = Issuer.get("get2", issuer2.id(), null);
            ctx.export("get2_selfsigned", get2.spec().applyValue(s -> s.selfSigned().isPresent()));
        });
    }
}

class Issuer extends CustomResource {
    /**
     * The spec of the Issuer.
     */
    @export(name = "spec", refs = { Outputs.IssuerSpec.class }, tree = "[0]")
    private Output<Outputs.IssuerSpec> spec;

    public Output<Outputs.IssuerSpec> spec() {
        return this.spec;
    }

    public Issuer(String name, @nullable IssuerArgs args) {
        super(name, makeArgs(args));
    }

    public Issuer(String name, @nullable IssuerArgs args,
            @nullable com.pulumi.resources.CustomResourceOptions options) {
        super(name, makeArgs(args), options);
    }

    protected Issuer(String name, Output<String> id,
            @nullable com.pulumi.resources.CustomResourceOptions options) {
        super(name, "cert-manager.io/v1", "Issuer", id, options);
    }

    private static IssuerArgs makeArgs(@nullable IssuerArgs args) {
        var builder = args == null ? IssuerArgs.builder() : IssuerArgs.builder(args);
        return builder
            .apiVersion("cert-manager.io/v1")
            .kind("Issuer")
            .build();
    }

    public static Issuer get(String name, Output<String> id, @nullable com.pulumi.resources.CustomResourceOptions options) {
        return new Issuer(name, id, options);
    }
}

class IssuerArgs extends CustomResourceArgsBase {
    /**
     * The spec of the Issuer.
     */
    @import(name = "spec", required = true)
    @nullable 
    private Output<Inputs.IssuerSpecArgs> spec;

    public static Builder builder() {
        return new Builder();
    }

    public static Builder builder(IssuerArgs defaults) {
        return new Builder(defaults);
    }

    static class Builder extends CustomResourceArgsBase.Builder<IssuerArgs, Builder> {
        public Builder() {
            super(new IssuerArgs());
        }

        public Builder(IssuerArgs defaults) {
            super(new IssuerArgs(), defaults);
        }

        public Builder spec(@nullable Output<Inputs.IssuerSpecArgs> spec) {
            $.spec = spec;
            return this;
        }

        public Builder spec(Inputs.IssuerSpecArgs spec) {
            return spec(Output.of(spec));
        }

        @OverRide
        protected void copy(IssuerArgs args) {
            super.copy(args);
            $.spec = args.spec;
        }
    }
}

class Inputs {
    public static final class IssuerSpecArgs extends com.pulumi.resources.ResourceArgs {

        public static final IssuerSpecArgs Empty = new IssuerSpecArgs();

        @import(name = "selfSigned", required = true)
        private @nullable Output<SelfSignedArgs> selfSigned;

        public Optional<Output<SelfSignedArgs>> selfSigned() {
            return Optional.ofNullable(this.selfSigned);
        }

        private IssuerSpecArgs() {
        }

        private IssuerSpecArgs(IssuerSpecArgs $) {
            this.selfSigned = $.selfSigned;
        }

        public static Builder builder() {
            return new Builder();
        }

        public static Builder builder(IssuerSpecArgs defaults) {
            return new Builder(defaults);
        }

        public static final class Builder {
            private IssuerSpecArgs $;

            public Builder() {
                $ = new IssuerSpecArgs();
            }

            public Builder(IssuerSpecArgs defaults) {
                $ = new IssuerSpecArgs(Objects.requireNonNull(defaults));
            }

            public Builder selfSigned(@nullable Output<SelfSignedArgs> selfSigned) {
                $.selfSigned = selfSigned;
                return this;
            }

            public Builder selfSigned(SelfSignedArgs selfSigned) {
                return selfSigned(Output.of(selfSigned));
            }

            public IssuerSpecArgs build() {
                return $;
            }
        }
    }

    public static final class SelfSignedArgs extends com.pulumi.resources.ResourceArgs {

        public static final SelfSignedArgs Empty = new SelfSignedArgs();

        private SelfSignedArgs() {
        }

        private SelfSignedArgs(SelfSignedArgs $) {
        }

        public static Builder builder() {
            return new Builder();
        }

        public static Builder builder(SelfSignedArgs defaults) {
            return new Builder(defaults);
        }

        public static final class Builder {
            private SelfSignedArgs $;

            public Builder() {
                $ = new SelfSignedArgs();
            }

            public Builder(SelfSignedArgs defaults) {
                $ = new SelfSignedArgs(Objects.requireNonNull(defaults));
            }

            public SelfSignedArgs build() {
                return $;
            }
        }
    }
}

class Outputs {
    @CustomType
    static final class IssuerSpec {

        private @nullable SelfSigned selfSigned;

        private IssuerSpec() {
        }

        public Optional<SelfSigned> selfSigned() {
            return Optional.ofNullable(this.selfSigned);
        }

        public static Builder builder() {
            return new Builder();
        }

        public static Builder builder(IssuerSpec defaults) {
            return new Builder(defaults);
        }

        @CustomType.Builder
        public static final class Builder {
            private @nullable SelfSigned selfSigned;

            public Builder() {
            }

            public Builder(IssuerSpec defaults) {
                Objects.requireNonNull(defaults);
                this.selfSigned = defaults.selfSigned;
            }

            @CustomType.Setter
            public Builder selfSigned(@nullable SelfSigned selfSigned) {
                this.selfSigned = selfSigned;
                return this;
            }

            public IssuerSpec build() {
                final var _resultValue = new IssuerSpec();
                _resultValue.selfSigned = selfSigned;
                return _resultValue;
            }
        }
    }

    @CustomType
    static final class SelfSigned {

        private SelfSigned() {
        }

        public static Builder builder() {
            return new Builder();
        }

        public static Builder builder(SelfSigned defaults) {
            return new Builder(defaults);
        }

        @CustomType.Builder
        public static final class Builder {
            public Builder() {
            }

            public Builder(SelfSigned defaults) {
                Objects.requireNonNull(defaults);
            }

            public SelfSigned build() {
                final var _resultValue = new SelfSigned();
                return _resultValue;
            }
        }
    }
}

```

Gives the expected output:
```
❯ pulumi preview --diff
Previewing update (dev)

+ pulumi:pulumi:Stack: (create)
    [urn=urn:pulumi:dev::issue-2787-javaa::pulumi:pulumi:Stack::issue-2787-javaa-dev]
    + kubernetes:cert-manager.io/v1:Issuer: (create)
        [urn=urn:pulumi:dev::issue-2787-javaa::kubernetes:cert-manager.io/v1:Issuer::issuer1]
        [provider=urn:pulumi:dev::issue-2787-javaa::pulumi:providers:kubernetes::default_0_0_16_SNAPSHOT::04da6b54-80e4-46f7-96ec-b56ff0331ba9]
        apiVersion: "cert-manager.io/v1"
        kind      : "Issuer"
        metadata  : {
            annotations: {
                pulumi.com/autonamed: "true"
            }
            name       : "issuer1-dcda28b8"
            namespace  : "default"
        }
        spec      : {
            selfSigned: {}
        }
    + kubernetes:cert-manager.io/v1:Issuer: (create)
        [urn=urn:pulumi:dev::issue-2787-javaa::kubernetes:cert-manager.io/v1:Issuer::issuer2]
        [provider=urn:pulumi:dev::issue-2787-javaa::pulumi:providers:kubernetes::default_0_0_16_SNAPSHOT::04da6b54-80e4-46f7-96ec-b56ff0331ba9]
        apiVersion: "cert-manager.io/v1"
        kind      : "Issuer"
        metadata  : {
            annotations: {
                pulumi.com/autonamed: "true"
            }
            name       : "issuer2-a0d8c527"
            namespace  : "default"
        }
        spec      : {
            selfSigned: {}
        }
    --outputs:--        
    issuer1_name      : "issuer1-dcda28b8"
    issuer2_name      : "issuer2-a0d8c527"
    issuer2_selfsigned: true
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Remove core/v1/ComponentStatus resource
2 participants