kcl-lang / kcl

KCL Programming Language (CNCF Sandbox Project). https://kcl-lang.io
https://kcl-lang.io
Apache License 2.0
1.61k stars 112 forks source link

[FAQ] Read a file and crossplane function kcl in kcl example #1299

Closed vfarcic closed 4 months ago

vfarcic commented 4 months ago

General Question

Is it possible to read the contents of a file and use it as a value?

jgascon-nx commented 4 months ago

I think you would be looking for something like the file package in combination with something else like the yaml package. So you could have something like:

# config.yaml file 
foo: bar
struct:
  key: value
# main.k file
import file
import yaml

_config_filename: str = "${file.modpath()}/config.yaml"
_config = yaml.decode(file.read(_config_filename))

my_item = _config.foo
my_item2 = _config.struct.key
kcl run main.k
# Output:
# my_item: bar
# my_item2: value

You can also combine it with with the template package, which uses handlebarsjs under the hood.

jgascon-nx commented 4 months ago

Extra: This doesn't answer the question and it's a bit off-topic but I think it can be of interest for some people with my use case (And also I'm telling you because I blame you for making me fall in love with KCL through your videos :P):

I'm currently using KCL in combination with Crossplane and because of my use case I was really looking for these kind features that allowed me to split Compositions, Functions and inline code into multiple files in order to preserve syntax and improve the developer experience a little bit.

So thanks to these features you can do some crazy stuff like having a Compositon written in KCL, which uses a KCL Function which creates a Terraform Workspace with some TF code stored in a different file, while having a neat folder organization and preserving syntax:

Code here
_Note: Untested_ Folder structure: ``` composition/ ├── composition.k ├── input.k └── input.workspace.tf ``` Composition: ```py # composition.k import file import template import crossplane.v1.apiextensions_crossplane_io_v1_composition as xp _input_filename: str = "${file.modpath()}/composition/input.k" _input_workspace_filename: str = "${file.modpath()}/composition/input.workspace.tf" composition = xp.Composition { metadata: { # ... } spec: { # ... pipeline: [ { step: "kcl-render" functionRef.name: "function-kcl" input: { apiVersion: "krm.kcl.dev/v1alpha1" kind: "KCLRun" spec: { # Read the Function KCL code, use it as a template and insert the TF code: source: template.execute( \ file.read(_input_filename), \ { "TERRAFORM_INPUT": file.read(_input_workspace_filename) } \ ) # ... } } } # ... ] } } ``` KCL Function code chunk: ```py # input.k # ... _tf_workspace = { apiVersion: "tf.upbound.io/v1beta1" kind: "Workspace" metadata: { # ... } spec.forProvider: { source: "Inline" varmap: { # ... } # Template variable substituted through template.execute(FILE, VARIABLES): module: r'''{{{ TERRAFORM_INPUT }}}''' } } # ... ``` ... And the Terraform code: ```hcl # input.workspace.tf # ... variable "whatever" { # ... } # ... ```

It's probably not the best of the approaches to take, but it's just an example of what I think as a great synergy between KCL and Crossplane in part thanks to these system packages :)

Peefy commented 4 months ago

❤️ 👋 @vfarcic Thank you for your feedback and attention. @jgascon-nx Thank you for sharing your use case. I think it would be very helpful for the community.

vfarcic commented 4 months ago

@jgascon-nx Your use case is very similar to mine. I completely missed the "System Package" section in the docs. That's what I needed. Thanks a ton for the tips.

@Peefy You're doing a great job both with KCL and with the Crossplane function.

metacoma commented 4 months ago

Hey @jgascon-nx, just FYI, here's how I deal with kcl and crossplane resources https://github.com/mindwm/mindwm-gitops/blob/b6adfdae54704e17a0e85751c9e52343755d2480/crossplane/xrd_kcl_function.k