github.com/wmuizelaar/kpt@v0.0.0-20221018115725-bd564717b2ed/site/reference/annotations/apply-time-mutation/README.md (about)

     1  ---
     2  title: "`apply-time-mutation`"
     3  linkTitle: "apply-time-mutation"
     4  type: docs
     5  description: >
     6    Specify one or more substitutions to make at apply time using dependencies as input.
     7  ---
     8  
     9  The `config.kubernetes.io/apply-time-mutation` annotation specifies one or more
    10  substitutions to make at apply time using dependencies as input.
    11  
    12  ### Schema
    13  
    14  The annotation value accepts a list of substitutions, formatted as a YAML string.
    15  
    16  - (\[\][Substitution]), required
    17  
    18      A list of one or more substitutions to perform on the annotated object.
    19  
    20  #### Substitution
    21  
    22  A substitution is a modification to a specific target field.
    23  
    24  -   **sourceRef**: ([ObjectReference]), required
    25  
    26      Reference to the source resource, the dependency for this substitution.
    27  
    28  -   **sourcePath**: (string), required
    29  
    30      The source resource field to read from as input, specified with [JSONPath].
    31  
    32  -   **targetPath**: (string), required
    33  
    34      The target resource field to write to as output, specified with [JSONPath].
    35  
    36  -   **token**: (string)
    37  
    38      The substring to replace in the target resource field.
    39  
    40      If the token is unspecified, the whole target field value will be replaced,
    41      allowing for replacement of non-string values using the source field type.
    42  
    43  #### ObjectReference
    44  
    45  A reference to a specific resource object.
    46  
    47  -   **apiVersion**: (string)
    48  
    49      The group and version of the object resource.
    50  
    51      One of the following is required: apiVersion or group.
    52  
    53  -   **group**: (string)
    54  
    55      The group of the object resource.
    56  
    57      Group is accepted as a version-less alternative to APIVersion.
    58  
    59      Group must be empty for resources in the "core" group.
    60  
    61      One of the following is required: apiVersion or group.
    62  
    63  -   **kind**: (string), required
    64  
    65      The kind of the object resource.
    66  
    67  -   **name**: (string), required
    68  
    69      The name of the object.
    70  
    71  -   **namespace**: (string)
    72  
    73      The namespace of the object.
    74  
    75      Namespace is required for namespaced resources.
    76  
    77  ### Behavior
    78  
    79  Like the `depends-on` feature, `apply-time-mutation` waits for dependencies 
    80  (source resources) to be applied and reconciled before applying the resource
    81  with the annotation.
    82  
    83  Unlike the `depends-on` feature, `apply-time-mutation` modifies the annotated
    84  resource before applying it.
    85  
    86  #### Special cases
    87  
    88  If the source resource is not part of the package being applied, the apply of
    89  the target resource will fail with an error. 
    90  
    91  The `apply-time-mutation` annotation is only enforced by `kpt live apply` and
    92  `kpt live destroy`. Modifying or deleting these resources with other mechanisms
    93  will not follow the rules specified by these annotations.
    94  
    95  ### JSONPath syntax
    96  
    97  Since there is no formal specification for JSONPath, the supported syntax
    98  depends on the chosen implimentation. In this case, kpt uses the
    99  [ajson](https://github.com/spyzhov/ajson) library. For details about what
   100  language features are supported, see the
   101  [json-path-comparison table](https://cburgmer.github.io/json-path-comparison/).
   102  
   103  ### Example
   104  
   105  In this example, pod-b depends on pod-a with two substitutions that replace
   106  tokens in the same target field. The value of the SERVICE_HOST environment
   107  variable of a container in pod-b will be updated to represent the host and port
   108  from pod-a.
   109  
   110  Create a new kpt package:
   111  
   112  ```shell
   113  mkdir my-pkg
   114  cd my-pkg
   115  kpt pkg init
   116  ```
   117  
   118  Configure two pods, with one that depends on the other:
   119  
   120  ```shell
   121  cat > pods.yaml << EOF
   122  kind: Pod
   123  apiVersion: v1
   124  metadata:
   125    name: pod-a
   126    namespace: test
   127  spec:
   128    containers:
   129    - name: nginx
   130      image: nginx:1.21
   131      ports:
   132      - name: tcp
   133        containerPort: 80
   134  ---
   135  apiVersion: v1
   136  kind: Pod
   137  metadata:
   138    name: pod-b
   139    namespace: test
   140    annotations:
   141      config.kubernetes.io/apply-time-mutation: |
   142        - sourceRef:
   143            kind: Pod
   144            name: pod-a
   145          sourcePath: $.status.podIP
   146          targetPath: $.spec.containers[?(@.name=="nginx")].env[?(@.name=="SERVICE_HOST")].value
   147          token: ${pod-a-ip}
   148        - sourceRef:
   149            kind: Pod
   150            name: pod-a
   151          sourcePath: $.spec.containers[?(@.name=="nginx")].ports[?(@.name=="tcp")].containerPort
   152          targetPath: $.spec.containers[?(@.name=="nginx")].env[?(@.name=="SERVICE_HOST")].value
   153          token: ${pod-a-port}
   154  spec:
   155    containers:
   156    - name: nginx
   157      image: nginx:1.21
   158      ports:
   159      - name: tcp
   160        containerPort: 80
   161      env:
   162      - name: SERVICE_HOST
   163        value: "${pod-a-ip}:${pod-a-port}"
   164  EOF
   165  ```
   166  
   167  Create a namespace for your package:
   168  
   169  ```shell
   170  kubectl create namespace test
   171  ```
   172  
   173  Initialize the package inventory:
   174  
   175  ```shell
   176  kpt live init
   177  ```
   178  
   179  Apply the package to your Kubernetes cluster:
   180  
   181  ```shell
   182  kpt live apply
   183  ```
   184  
   185  If all goes well, the output should look like this:
   186  
   187  ```
   188  pod/pod-a created
   189  1 resource(s) applied. 1 created, 0 unchanged, 0 configured, 0 failed
   190  pod/pod-b created
   191  1 resource(s) applied. 1 created, 0 unchanged, 0 configured, 0 failed
   192  ```
   193  
   194  To verify that the SERVICE_HOST was mutated correctly:
   195  
   196  ```shell
   197  # Read the IP of pod-a
   198  kubectl get pod pod-a -n test \
   199    -o jsonpath='{.status.podIP}'
   200  ```
   201  
   202  ```shell
   203  # Read the SERVICE_HOST of pod-b
   204  kubectl get pod pod-b -n test \
   205    -o jsonpath='{.spec.containers[?(@.name=="nginx")].env[?(@.name=="SERVICE_HOST")].value}'
   206  ```
   207  
   208  Delete the package from your Kubernetes cluster:
   209  
   210  ```shell
   211  kpt live destroy
   212  ```
   213  
   214  If all goes well, the output should look like this:
   215  
   216  ```
   217  pod/pod-b deleted
   218  1 resource(s) deleted, 0 skipped
   219  pod/pod-a deleted
   220  1 resource(s) deleted, 0 skipped
   221  ```
   222  
   223  [Substitution]: /reference/annotations/apply-time-mutation/#substitution
   224  [ObjectReference]: /reference/annotations/apply-time-mutation/#objectreference
   225  [JSONPath]: /reference/annotations/apply-time-mutation/#jsonpath-syntax