Carvel Logo

Library Module

Overview

You can extract a whole set of input files (i.e. templates, overlays, data values, etc.) into a “Library”.

For example:

config/
├── _ytt_lib/
│   └── frontend/
│       ├── schema.yml
│       └── store.yml
└── config.yml

where:

  • config/_ytt_lib/frontend/ and its contents is a library named "frontend"

Libraries are not automatically included in ytt output; one must programmatically load, configure, evaluate, and insert those results into a template that is part of the output.

#! config/config.yml -- example of using a library

#@ load("@ytt:library", "library")
#@ load("@ytt:template", "template")

#! 1. Load an instance of the library
#@ app = library.get("frontend")

#! 2. Create a configured copy of the library (does not mutate original)
#@ app_with_vals = app.with_data_values({"apiDomain": "gateway.example.com"})

#! 3. Evaluate the library and include results (a document set) in the output
--- #@ template.replace(app_with_vals.eval())

For a complete working example, see ytt-library-module example.

What is a Library?

A ytt library is a directory tree contained within a specially-named directory: _ytt_lib/.

  • The library’s name is the path relative from the _ytt_lib/ directory.
  • The library’s contents are those of the directory along with subdirectories, recursively.
  • A library may contain libraries as well, if one of its subdirectories is _ytt_lib/.

The root directory of a ytt invocation is itself a library known as the “root library”.

Libraries are evaluated in isolation: each a separate execution of the pipeline described in How it works.

  • Each library has its own data values schema.
  • Overlays within a library only apply over its evaluated document set.
  • The final evaluated result is returned as a YAML Fragment wrapping a document set..

Functions

There’s but one function in the @ytt:library module: library.get()

library.get()

Contructs a new @ytt:library.instance based on the contents from the named library.

instance = library.get(name, [<kwargs>])
  • name (string) — path to the base directory of the desired library: ./_ytt_lib/<name>. Can contain slashes / for sub-directories (e.g. github.com/carvel-dev/ytt-library-for-kubernetes/app)
  • keyword arguments (optional):
    • alias= (string) — unique name for this library instance. See Aliases, below.
    • ignore_unknown_comments= (bool) — equivalent to ytt --ignore-unknown-comments; see File Marks > type detection for YAML files for more details (default: False). (as of v0.31.0)
    • implicit_map_key_overrides= (bool) — equivalent to ytt --implicit-map-key-overrides; see @yaml/map-key-override for more details. (default: False). (as of v0.31.0)
    • strict= (bool) — equivalent to ytt --strict (default: False). (as of v0.31.0)
  • instance (@ytt:library.instance) — a new library instance backed by the contents of the named library.

The file containing this method invocation must be a sibling of the _ytt_lib directory.


Library Instances

Each library returned from a function within this module is a copy: a separate instance.

A library instance (a value of type @ytt:library.instance) is created from source with library.get().

With a library instance:

instance.data_values()

Calculates and returns just the Data Values configured on this library instance.

dvs = instance.data_values()

instance.eval()

Calculates the library’s final data values (i.e. the net result of all configured data values), evaluates its templates into a document set, and applies its overlays on that document set (i.e. executes the pipeline described in How it works for this library instance’s inputs and contents).

document_set = instance.eval()
  • document_set (yamlfragment) — the YAML document set resulting from the evaluation of this instance.

instance.export()

(As of v0.28.0)

Returns the value of an identifier declared within the library instance.

value = instance.export(name, [path=])
  • name (string) — the name of a function or a variable declared within some module/file in the library. (i.e. a file with the extension .lib.yml or .star).
  • path= (string) — the path to the module/file that contains the declaration. Only required when name is not unique within the library.
  • value (any) — a copy of the specified value.
    • if value is a function, it is executed within the context of its library instance. For example, if the function depends on values from the @ytt:data module, the values provided are those of this library instance.

Examples:

Example 1: Exporting a function from a library.

Assuming some module/file in the “helpers” library contains the definition:

...
def wrap_name(name):
   ...
end
...

Can be exported and used from another library:

helpers = library.get("helpers")
wrap_name = helpers.export("wrap_name")

full_name = wrap_name("app")

Example 2: Disambiguating between multiple declarations of function.

Assuming two modules/files in the “helpers” library have the same name:

# main/funcs.star
def wrap_name(name): ...

and

# lib/funcs.star
def wrap_name(name): ...

One of which can be unambiguously referenced:

helpers = library.get("helpers")
wrap_name = helpers.export("wrap_name", path="lib/funcs.star")

full_name = wrap_name("app")

Note: without the path= keyword argument, helpers.export() would report an error.

instance.with_data_values()

Returns a copy of the library instance with data values overlayed with those given.

new_instance = instance.with_data_values(dvs, [plain=])
  • dvs (struct | yamlfragment) — data values with which to overlay (or set, if none exist).
    • only yamlfragments wrapping a map or an array are supported (i.e. yamlfragments wrapping document sets are not supported).
    • yamlfragment values can contain overlay annotations for fine-grained overlay control.
  • plain= (bool) — when True indicates that dvs should be “plain merged” over existing data values (i.e. the exact same behavior as --data-values-file).
    • dvs must be plain YAML (i.e. a struct or a yamlfragment with no annotations).
  • new_instance (@ytt:library.instance) — a copy of instance with dvs overlayed on its data values; instance remains unchanged.

instance.with_data_values_schema()

(As of v0.35.0)

Returns a copy of the library instance with data values schema overlayed with that given.

new_instance = instance.with_data_values_schema(schema)
  • schema (struct | yamlfragment) — schema for data values with which to overlay on existing schema (or set if none exist).
    • only yamlfragments wrapping a map or an array are supported (i.e. yamlfragments wrapping document sets are not supported)
    • yamlfragment values can contain overlay annotations for fine-grained overlay control.
  • new_instance (@ytt:library.instance) — a copy of instance with a schema updated with schema; instance remains unchanged.

Examples:

Example 1: Declaring a new data value (and setting it).

#@ def app_schema():
name: ""
#@overlay/match missing_ok=True
env_vars:
  custom_key: ""
#@ end

#@ app1_with_schema = app1.with_data_values_schema(app_schema())
---
#@ def app_vals():
name: app1
env_vars:
  custom_key: some_val
#@ end

#@ app1_with_vals = app1.with_data_values(app_vals())

Annotations

@library/ref

(As of v0.28.0)

Attaches a YAML document to the specified library. When the library is evaluated, the annotated document is included. Only supported on documents annotated with @data/values and @data/values-schema.

@library/ref library_name
  • library_name (string) — @-prefixed path to the base directory of the desired library: ./_ytt_lib/<name>. Can contain slashes / for sub-directories (e.g. github.com/carvel-dev/ytt-library-for-kubernetes/app). Can also be an alias for specific library instance(s).

Examples:

Example 1: Change schema default for a data value in a library.

#@data/values-schema
#@library/ref "@frontend"
---
name: "custom"

Overlays the default value for name in the “frontend” library to be “custom”.

Example 2: Target a data value overlay to a library.

#@data/values
#@library/ref "@backend"
---
#@overlay/replace
domains:
- internal.example.com
- internal-backup.example.com

Sets the “backend” library’s domains data value to be exactly the values given.

See also: Data Values > Setting Library Values via Files.

Note: data values may also be attached to libraries via command line flags.


Aliases

To facilitate configuring specific library instances, one can mark them with an alias.

An alias:

  • is defined in a library.get() call, using the optional alias= keyword argument.
  • is added to a library reference by prefixing it with a tilde, ~:
    • @~<alias-name> refers to any library instance with the alias.
    • @<library-name>~<alias-name> refers to any instance of the named library that also has the alias.

For example, given a library known as “fruit”:

├── apple-values.yml
├── config.yml
├── orange-values.yml
└── _ytt_lib
    └── fruit
        ├── doc.yml
        └── values.yml

where:

#! _ytt_lib/fruit/doc.yml

#@ load("@ytt:data", "data")
--- #@ data.values

the template in the library simply returns its data values as a document, and …

#! _ytt_lib/fruit/values.yml

#@data/values
---
variety: ordinary
poisoned: false

… those are the data values in the library.

The root library can assign aliases to library instances:

#! ./config.yml

#@ load("@ytt:library", "library")

#@ apple1 = library.get("fruit", alias="apple")
#@ apple2 = apple1.with_data_values({"variety": "jonamac"})

#@ orange = library.get("fruit", alias="orange")

---
apple:
  1: #@ apple1.eval()[0]
  2: #@ apple2.eval()[0]
orange: #@ orange.eval()[0]

where:

  • apple1 has the alias “apple”
  • apple2 also has the alias “apple” (part of being a copy of apple1)
  • orange has the alias “orange”

These aliases can be used to target changes to specific library instance(s).

For example, our root library has these two data values overlays:

#! ./apple-values.yml

#@data/values
#@library/ref "@~apple"
---
variety: red delicious
poisoned: true

… which will affect all library instances with the alias “apple”, and …

#! ./orange-values.yml

#@data/values
#@library/ref "@~orange"
---
variety: valencia

… overlays on top of library instance with the alias “orange”.

When the whole fileset is evaluated, the result is:

apple:
  1:
    variety: red delicious
    poisoned: true
  2:
    variety: jonamac
    poisoned: true
orange:
  variety: valencia
  poisoned: false

notice:

  • only the “@~orange” instance has the variety = “valencia”
  • both “@~apple” library instances are poisoned; while the “orange” instance is not.

(Help improve our docs: edit this page on GitHub)