github.com/wmuizelaar/kpt@v0.0.0-20221018115725-bd564717b2ed/site/book/04-using-functions/02-imperative-function-execution.md (about)

     1  The `fn eval` command enables you to execute a single function without declaring
     2  it in the package. This is referred to as imperative function execution.
     3  
     4  For example, to set the namespace of all resources in the wordpress package
     5  hierarchy:
     6  
     7  ```shell
     8  $ kpt fn eval wordpress --image gcr.io/kpt-fn/set-namespace:v0.1 -- namespace=mywordpress
     9  ```
    10  
    11  Alternatively, for convenience, you can use the short-hand form of the above command:
    12  
    13  ```shell
    14  $ kpt fn eval wordpress -i set-namespace:v0.1 -- namespace=mywordpress
    15  ```
    16  
    17  ?> Refer to the [eval command reference][eval-doc] for usage.
    18  
    19  This changes the resources in the `wordpress` package and the `mysql`
    20  subpackage.
    21  
    22  For comparison, this has the same effect as the following declaration:
    23  
    24  ```yaml
    25  # wordpress/Kptfile (Excerpt)
    26  apiVersion: kpt.dev/v1
    27  kind: Kptfile
    28  metadata:
    29    name: wordpress
    30  pipeline:
    31    mutators:
    32      - image: gcr.io/kpt-fn/set-namespace:v0.1
    33        configMap:
    34          namespace: mywordpress
    35  ```
    36  
    37  So when should you execute a function using `eval` instead of `render`?
    38  
    39  When you have one of these use cases:
    40  
    41  - Perform a one-time operation
    42  - Execute a function from a CI/CD system on packages authored by other teams
    43  - Develop shell scripts and chain functions with the Unix pipe (`|`)
    44  - Execute the function with privilege (Not allowed by `render`)
    45  
    46  We will cover these topics in detail.
    47  
    48  ## Specifying `functionConfig`
    49  
    50  There are two ways to specify the `functionConfig`.
    51  
    52  ### `fn-config` flag
    53  
    54  The general way to provide a `functionConfig` of arbitrary kind (core or custom
    55  resources), is to declare the resource in a separate file and use the
    56  `fn-config` flag.
    57  
    58  ```shell
    59  $ cat << EOF > /tmp/fn-config.yaml
    60  apiVersion: v1
    61  kind: ConfigMap
    62  metadata:
    63    name: ns
    64  data:
    65    namespace: mywordpress
    66  EOF
    67  ```
    68  
    69  ```shell
    70  $ kpt fn eval wordpress -i set-namespace:v0.1 --fn-config /tmp/fn-config.yaml
    71  ```
    72  
    73  ### CLI arguments
    74  
    75  Many functions take a `functionConfig` of kind `ConfigMap` since they only need
    76  simple key/value pairs as argument. For convenience, there is a way to provide
    77  the key/value pairs as command line arguments. The following is equivalent to
    78  what we showed previously:
    79  
    80  ```shell
    81  $ kpt fn eval wordpress -i set-namespace:v0.1 -- namespace=mywordpress
    82  ```
    83  
    84  Note that the arguments must come after the separator `--`.
    85  
    86  ## Specifying `selectors`
    87  
    88  Selectors can be used to target specific resources for a function execution.
    89  
    90  For example, you can selectively add an annotation to the resources if it has kind
    91  `Deployment` AND name `wordpress`:
    92  
    93  ```shell
    94  $ kpt fn eval wordpress -i set-annotations:v0.1 --match-kind Deployment --match-name wordpress -- foo=bar
    95  ```
    96  
    97  Here is the list of available selector matcher flags:
    98  
    99  1. `match-api-version`
   100  2. `match-kind`
   101  3. `match-name`
   102  4. `match-namespace`
   103  5. `match-annotations`
   104  6. `match-labels`
   105  
   106  ## Specifying `exclusions`
   107  
   108  Exclusions can be used to exclude specific resources for a function execution.
   109  
   110  For example, you can set the namespace of all resources in the wordpress package, 
   111  except for the ones with the label `foo: bar`:
   112  
   113  ```shell
   114  $ kpt fn eval wordpress -i set-namespace:v0.1 --exclude-labels foo=bar -- namespace=my-namespace
   115  ```
   116  
   117  If you use multiple exclusions, it will exclude resources that match all provided exclusions. For
   118  example, you can set the namespace of all resources, except for those that have both kind "Deployment" 
   119  and name "nginx":
   120  
   121  `$ kpt fn eval wordpress -i set-namespace:v0.1 --exclude-kind Deployment --exclude-name nginx -- namespace=my-namespace`
   122  
   123  Here is the list of available exclusion flags:
   124  
   125  1. `exclude-api-version`
   126  2. `exclude-kind`
   127  3. `exclude-name`
   128  4. `exclude-namespace`
   129  5. `exclude-annotations`
   130  6. `exclude-labels`
   131  
   132  ## Privileged Execution
   133  
   134  Since the function is provided explicitly by the user, `eval` can be more
   135  privileged and low-level than a declarative invocation using `render`. For
   136  example, it can have access to the host system.
   137  
   138  In general, we recommend against having functions that require privileged access
   139  to the host since they can only be executed imperatively and pose a challenge in
   140  terms of security, correctness, portability and speed. If at all possible,
   141  functions should be executed hermetically with all required dependencies either
   142  passed in as KRM resources (input items or functionConfig) or included in the
   143  container image. However, there are some legitimate use cases where the only
   144  available option requires either network access or mounting a volume from the
   145  host. In those situations, you can use `eval` as described below.
   146  
   147  ### Network Access
   148  
   149  By default, functions cannot access the network. You can enable network access
   150  using the `--network` flag.
   151  
   152  For example, `kubeval` function can download a JSON schema file:
   153  
   154  ```shell
   155  $ kpt fn eval wordpress -i kubeval:v0.1 --network -- schema_location="https://kubernetesjsonschema.dev"
   156  ```
   157  
   158  ### Mounting Directories
   159  
   160  By default, functions cannot access the host file system. You can use the
   161  `--mount` flag to mount host volumes. kpt accepts the same options to `--mount`
   162  specified on the [Docker Volumes] page.
   163  
   164  For example, `kubeval` function can consume a JSON schema file:
   165  
   166  ```shell
   167  $ kpt fn eval -i kubeval:v0.1 --mount type=bind,src="/path/to/schema-dir",dst=/schema-dir --as-current-user wordpress -- schema_location=file:///schema-dir
   168  ```
   169  
   170  Note that the `--as-current-user` flag may be required to run the function as
   171  your uid instead of the default `nobody` to access the host filesystem.
   172  
   173  All volumes are mounted readonly by default. Specify `rw=true` to mount volumes
   174  in read-write mode.
   175  
   176  ```
   177  --mount type=bind,src="/path/to/schema-dir",dst=/schema-dir,rw=true
   178  ```
   179  
   180  ## Chaining functions using the Unix pipe
   181  
   182  As an alternative to declaring a pipeline in the `Kptfile`, you can chain
   183  functions using the Unix pipe.
   184  
   185  Here is an example:
   186  
   187  ```shell
   188  $ kpt fn source wordpress \
   189    | kpt fn eval - -i set-namespace:v0.1 -- namespace=mywordpress \
   190    | kpt fn eval - -i set-labels:v0.1 -- app=wordpress env=prod \
   191    | kpt fn sink my-wordpress
   192  ```
   193  
   194  ?> Refer to the command reference for usage of [source][source-doc] and
   195  [sink][sink-doc] commands.
   196  
   197  The following describes the above pipeline:
   198  
   199  1. The `source` command is used to read the resources in the package hierarchy
   200     (`wordpress` and `mysql` packages). The output of the `source` command
   201     follows the KRM Function Specification standard, which we are going to look
   202     at in chapter 5.
   203  2. The output of the `source` function is piped into the `set-namespace`
   204     function. `eval` function is instructed to read inputs items from the `stdin`
   205     using `-`. This is the convention used in all commands in kpt that can read
   206     from `stdin`. The `set-namespace` function mutates the input items and emits
   207     the output items.
   208  3. The output of the `set-namespace` function is piped into `set-labels`
   209     function which adds the given labels to all resources.
   210  4. The `sink` command writes the output of `set-labels` to the filesystem.
   211  
   212  This is a low-level and less abstracted approach to executing functions. You can
   213  instead write the output of the pipeline to a different directory instead of
   214  mutating the directory in-place. You can also pipe to other programs (e.g.
   215  `sed`, `yq`) that are not functions. Be mindful that the cost of this low-level
   216  flexibility is not having benefits provided by functions: scalability,
   217  reusability, and encapsulation.
   218  
   219  [eval-doc]: /reference/cli/fn/eval/
   220  [source-doc]: /reference/cli/fn/source/
   221  [sink-doc]: /reference/cli/fn/sink/
   222  [docker volumes]: https://docs.docker.com/storage/volumes/