How to force complete recreation of custom resource during stack updates? - aws-cloudformation

I have a CF template with a custom resource (backed by a lambda function).
I would like this custom resource to be deleted and the newly created when I update my stack.
How can I achieve this?
To make this practical, let's assume I have a custom resource which simply produces a random string.
More or less as described here:
https://www.itonaut.com/2018/01/03/generate-passwords-in-aws-cloudformation-template/
So I have a resource like:
RandomSuffix:
Type: AWS::CloudFormation::CustomResource
DeletionPolicy: Delete
Properties:
Length: 3
ServiceToken: !ImportValue
'Fn::Sub': 'cf-utils-RandomStringFunction-Arn'
In general, this works, I get some random string as RandomSuffix.Value.
However, after an update, this values stays the same.
Is there any way to force deletion and recreation of my custom resource during update?

You need to change it's name. e.g. RandomSuffix=>RandomSuffix20191210

Related

Kubernetes: validating update requests to custom resource

I created a custom resource definition (CRD) and its controller in my cluster, now I can create custom resources, but how do I validate update requests to the CR? e.g., only certain fields can be updated.
The Kubernetes docs on Custom Resources has a section on Advanced features and flexibility (never mind that validating requests should be considered a pretty basic feature 😉). For validation of CRDs, it says:
Most validation can be specified in the CRD using OpenAPI v3.0 validation. Any other validations supported by addition of a Validating Webhook.
The OpenAPI v3.0 validation won't help you accomplish what you're looking for, namely ensuring immutability of certain fields on your custom resource, it's only helpful for stateless validations where you're looking at one instance of an object and determining if it's valid or not, you can't compare it to a previous version of the resource and validate that nothing has changed.
You could use Validating Webhooks. It feels like a heavyweight solution, as you will need to implement a server that conforms to the Validating Webhook contract (responding to specific kinds of requests with specific kinds of responses), but you will have the required data at least to make the desired determination, e.g. knowing that it's an UPDATE request and knowing what the old object looked like. For more details, see here. I have not actually tried Validating Webhooks, but it feels like it could work.
An alternative approach I've used is to store the user-provided data within the Status subresource of the custom resource the first time it's created, and then always look at the data there. Any changes to the Spec are ignored, though your controller can notice discrepancies between what's in the Spec and what's in the Status, and embed a warning in the Status telling the user that they've mutated the object in an invalid way and their specified values are being ignored. You can see an example of that approach here and here. As per the relevant README section of that linked repo, this results in the following behaviour:
The AVAILABLE column will show false if the UAA client for the team has not been successfully created. The WARNING column will display a warning if you have mutated the Team spec after initial creation. The DIRECTOR column displays the originally provided value for spec.director and this is the value that this team will continue to use. If you do attempt to mutate the Team resource, you can see your (ignored) user-provided value with the -o wide flag:
$ kubectl get team --all-namespaces -owide
NAMESPACE NAME DIRECTOR AVAILABLE WARNING USER-PROVIDED DIRECTOR
test test vbox-admin true vbox-admin
If we attempt to mutate the spec.director property, here's what we will see:
$ kubectl get team --all-namespaces -owide
NAMESPACE NAME DIRECTOR AVAILABLE WARNING USER-PROVIDED DIRECTOR
test test vbox-admin true API resource has been mutated; all changes ignored bad-new-director-name

REST API - How to handle optional parameter in PUT method ? what is difference in implementation with PATCH method

I'm a little confused about put method with optional paramter.
suppose the mode is
Pet {
name
catagory
tag (optional)
}
when I want to create a Pet, I can use post method, the tag can be omitted.
when I want to update a Pet, the problem comes to me. According to the http spec, PUT method will update the entity by replaces the whole resource, which means I need to pass tag parameter. If I didn't pass tag, the default value will be empty, but it will cause the existing tag be override to empty.
For patch method, it will only update partial parameter no matter if it is optional. It's clear to understand.
I don't know if I misunderstand something, currently, in PUT method, I need to figure out what parameter is passed, and then update correspond field. But this seems the same with PATCH method.
An important thing to understand is that the HTTP specification describes the semantics (what do the different requests mean), but does not describe the implementation (how do you do it). That's deliberate - the specification basically says that your server should pretend to be a key/value store, but it doesn't restrict how you implement that.
PUT is roughly analogous to saving a file: "here is an array of bytes, save it using this key". In cases where your storage is a file system, then you just write the array of bytes to disk. If your storage is an in memory cache, then you just update your cached copy.
If your storage is some RDBMS database? Then you have some work to do, identifying which rows in your database need to be changed, and what commands need to be sent to the database to make that happen.
The point is that the client doesn't care -- as a server, you can change your underlying storage from RDBMS to document stores to files systems to whatever, and that's not any of the client's business.
in PUT method, I need to figure out what parameter is passed, and then update correspond field. But this seems the same with PATCH method.
Yes. In both cases, you need to figure out how to edit your resource in place.
PUT may feel a little bit easier, in that it is semantically equivalent to "delete the old version, then create a new version". You don't have to worry about merging the provided data to the state you already have stored.

When exactly do I set an ownerReference's controller field to true?

I am writing a Kubernetes controller.
Someone creates a custom resource via kubectl apply -f custom-resource.yaml. My controller notices the creation, and then creates a Deployment that pertains to the custom resource in some way.
I am looking for the proper way to set up the Deployment's ownerReferences field such that a deletion of the custom resource will result in a deletion of the Deployment. I understand I can do this like so:
ownerReferences:
- kind: <kind from custom resource>
apiVersion: <apiVersion from custom resource>
uid: <uid from custom resource>
controller: <???>
I'm unclear on whether this is case where I would set controller to true.
The Kubernetes reference documentation says (in its entirety):
If true, this reference points to the managing controller.
Given that a controller is running code, and an owner reference actually references another Kubernetes resource via matching uid, name, kind and apiVersion fields, this statement is nonsensical: a Kubernetes object reference can't "point to" code.
I have a sense that the documentation author is trying to indicate that—using my example—because the user didn't directly create the Deployment herself, it should be marked with some kind of flag indicating that a controller created it instead.
Is that correct?
The follow on question here is of course: OK, what behavior changes if controller is set to false here, but the other ownerReference fields are set as above?
ownerReferences has two purposes:
Garbage collection: Refer to the answer of ymmt2005. Essentially all owners are considered for GC. Contrary to the accepted answer the controller field has no impact on GC.
Adoption: The controller field prevents fighting over resources which are to be adopted. Consider a replica set. Usually, the replica set controller creates the pods. However, if there is a pod which matches the label selector it will be adopted by the replica set. To prevent two replica sets fighting over the same pod, the latter is given a unique controller by setting the controller to true. If a resource already has a controller it will not be adopted by another controller. Details are in the design proposal.
TLDR: The field controller is only used for adoption and not GC.
According to the source code of Kubernetes, the object will be garbage collected only after all objects in ownerReferences field are deleted.
https://github.com/kubernetes/apimachinery/blob/15d95c0b2af3f4fcf46dce24105e5fbb9379af5a/pkg/apis/meta/v1/types.go#L240-L247
// List of objects depended by this object. If ALL objects in the list have
// been deleted, this object will be garbage collected. If this object is managed by a controller,
// then an entry in this list will point to this controller, with the controller field set to true.
// There cannot be more than one managing controller.
According to the documentation:
Sometimes, Kubernetes sets the value of ownerReference automatically. For example, when you create a ReplicaSet, Kubernetes automatically sets the ownerReference field of each Pod in the ReplicaSet. In 1.6, Kubernetes automatically sets the value of ownerReference for objects created or adopted by ReplicationController, ReplicaSet, StatefulSet, DaemonSet, and Deployment.
You can also specify relationships between owners and dependents by manually setting the ownerReference field.
Basically, a Deployment is on the top of the ownership hierarchy, and ownerReference is not set to it automatically. Therefore, you can manually add ownerReference to your Deployment to create the reference to your Foo resource.
You asked:
The follow on question here is of course: OK, what behavior changes if controller is set to false here, but the other ownerReference fields are set as above?
OwnerReference is used by a Garbage Collector. The role of the Kubernetes Garbage Collector is to delete certain objects that once had an owner, but no longer have it.
Here is the link to the description of the OwnerReference structure on Github. As you mentioned, if controller: true, the reference points to the managing controller, in other words, the owner. And also, it is the instruction for Garbage Collector's behavior related to the object and its owner. If controller: false, Garbage Collector manages the object as an object without an owner, for example, allows to delete it freely.
For more information, you can visit the following links:
- Garbage Collection
- Deletion and Garbage Collection of Kubernetes Objects

kubernetes strategic merge patch

Hi I am following this doc https://github.com/kubernetes/kubernetes/blob/master/docs/devel/api-conventions.md#strategic-merge-patch for strategic-merge-patch to partially update the JSON objects using PATCH REST API. The document says that it can add or delete the object, but I have tried, whenever I add new object to existing JSON it just replaces that instead of adding new. I am trying this to modify pod definition in OpenShift 3.2. can anyone please help me how it works, probably with example. I need to use delete operation also , where I can delete the value by name.
As documented it depends on annotations of the types. AFAIS the strategic merge only works if patchStrategy and patchMergeKey are given. For example, this is the case in pod.spec.containers and pod.spec.volumes.
For an example you need to provide more information about the type you want to merge.

Change a resource by deletion of existing followed by insertion of new. Still a PUT?

I'm working on a REST-like API.
This API have a this for changing a existing resource by ID:
/api/v1/admin/member/:ID
I any normal circumstances this would of course be a PUT when changing a resource.
But because of a compromise leading to simpler code, this route actually first delete the resource completely (and all references to it) and then create a new one based on the input given by a form.
In all means this will look and give the same end result as a resource change.
Question: Should this route be a PUT or a POST
The expected behavior is idempotent so I would say use PUT, and I would make sure the update occurs in a transaction so an error between deleting and inserting would not leave the resource deleted.