►
From YouTube: Primer on ytt Overlays by John Ryan
Description
Ever been frustrated writing an ytt Overlay? Here's that primer you wish you had.
A
A
So
what
I
wanted
to
do
is
demystify
that,
by
working
through
a
progressive
example,
really
quick
before
we
do
that
these
are
the
docs
that
talk
about
overlays.
If
you
haven't
seen
this,
it's
really
worthwhile
that
we
try
to
be
to
the
point-
and
this
gives
you
an
example
of
how
to
read
an
overlay,
there's
actually
a
whole
bunch
of
examples
of
overlays
in
our
playground.
A
A
It's
like
this
one
in
particular,
this
has
a
deployment
and
a
service
they're
all
tied
together
and
the
deployment
is
running
nginx
and
it's
got
a
command
specified
and
some
ports
and
there's
three
instances
anyway.
So
then
there's
a
service
that
is
providing
that
domain
name
to
reach
that
deployment.
A
A
A
So
the
first
is
this
by
keyword,
which
is
the
criteria
that
we're
going
to
match
with
it's
usually
a
function,
there's
a
string
option,
but
you're
almost
always
using
a
function
and
then
the
second
is
this
expectation-
and
this
is
the
number
of
items
that
our
matcher
expects
to
match
by
default.
It'll
be
one,
and
there
are
a
couple
other
keywords
we'll
get
into
later.
But
these
are
the
main
two
right
now
is
our
buy
and
expects?
A
A
So
the
message
is
pointing
at
line
four,
which
is
a
document
node.
So
I
like
to
read
the
next
part
of
the
message
replacing
the
word
nodes
with
that
type,
so
expected
number
of
matched
documents
to
be
one,
but
was
two
what's
going
on
here.
It's
saying
that
the
default
expectation
is
one,
but
there
are
actually
two
documents
present.
A
A
A
The
content
of
this
document
is
a
map
with
a
bunch
of
map
items,
but
null
merged
onto
a
map
or
any
value
is
null,
and
so
that
means
this
document
gets
merged
into
null
and
then,
when
this
overlay
is
applied
to
this
document,
it
gets
merged
to
null,
and
so
we
have
a
bunch
of
null
documents
and
so
there's
no
output.
This
is
not
what
we
want.
What
we
want
to
do
is
patch
into
a
piece
of
this
map,
specifically
the
metadata.
We
want
to
put
a
metadata
key
in
here,
so
we'll
do
that
next.
A
A
The
default
action
is
to
merge.
I
was
just
saying
that
before
and
each
node
has
its
own
pair
of
matcher
and
action,
this
one
doesn't
have
any
annotations,
but
they're
implied
since
it's
inside
of
an
overlay,
but
they
would
look
like
this
if
we
wrote
them
out
explicitly
so
that
is,
it
would
match
and
when
a
matcher
is
annotating
a
map
item,
the
default
criteria
is
to
match
the
key
name
and,
as
we
saw
before,
the
default
expectation
is
that
would
match
exactly
one
map
item
in
the
target
and
the
default
action
is
merge.
A
A
Okay,
let's
break
this
down
again
line
eight
oops
line,
nine
expected
number
of
match
nodes
to
be
one,
but
was
zero.
Let's
put
in
our
defaults
again
and
see
if
that
helps
us
okay,
so
this
makes
it
really
clear
that
our
default
expectation
of
one
isn't
going
to
work
here,
because
there
is
no
namespace
in
this
document.
Well,
it's
not
there's,
there's
no
namespace
in
either
one
of
these
right
now
so
yeah.
A
A
So
this
works
great,
except
it's
a
little
bit
brittle
because
it's
quite
possible
that,
even
if
it
isn't
happening
today
that
upstream,
they
might
actually
include
the
namespace,
that's
not
unreasonable,
and
at
that
point
our
overlay
is
going
to
fail,
and
that's
because
when
we
attempt
to
match
on
this
document,
this
will
merge.
The
metadata
will
merge
and
get
down
to
namespace,
and
our
expectation
is
that
there
is
no
map
item
with
the
key
namespace,
but
there
will
be
exactly
one.
A
So
in
that
case
we
would
want
to
replace
it
as
well.
So
we
can
actually
just
specify
that,
in
the
expectation
that
we
can
expect
zero
or
one
map
item
that
has
that
key
now.
This
is
such
a
common
scenario
that
we
actually
have
a
special
syntax
for
this,
and
that
is
this
missing.
Okay
keyword-
and
this
is
just
simply
a
shorthand
for
what
we
just
wrote
and
we
find
that
it's
more
telling
or
readable.
A
And
so
there
we
go
so
now
we
are
whether
there's
a
namespace
or
not
we're
ensuring
there
is
a
namespace,
and
then
it
has
our
staging
value.
Now,
there's
a
lot
of
annotations
going
on
here,
but
the
good
news
is
a
bunch
of
this
stuff
are
just
the
defaults.
So,
let's
start
with
the
actions.
Merge
is
the
default
action,
so
we
don't
need
to
specify
that
in
any
of
these
nodes
here
we
needed
to
configure
the
criteria
and
the
expectation
we
need
to
set
this
to
greater
than
one
so
at
least
one.
A
A
A
A
A
A
So
let's
write
that
out
so
overlay
dot
subset,
oh
and
we
need
that
we
want
to
load
the
module,
so
we
have
access
to
this
function,
and
so
now
we
want
to
write
that
fragment.
So
we'll
do
this
with
what
looks
like
json
notation
great,
but
this
is
actually
just
a
starlark
dictionary
where
this
is
the
key,
and
this
is
val
and
it
maps
perfectly
to
map
items
in
your
yaml,
so
there's
key
deployment.
A
So
we
see
here
that
this
overlay
is
matching
exactly
one
document
which
remember
is
the
default
expectation.
That's
great,
we'll
keep
that
and
and
that
it's
merging
remember
that
the
default
action
is
to
merge,
but
the
value
of
this
overlay
is
null
and
therefore
it
is
merging
null
into
this
map,
which
zeros,
which
makes
which
is
null,
and
so
therefore,
we
no
longer
see
the
deployment,
though
that's
not
what
we
want.
A
So
we
give
it
a
name.
We
identify
the
container
image
and
name
the
ports
that
it'll
listen
to
so
so
far,
we've
been
annotating
documents
and
map
items.
This
is
the
first
time
we've
added
an
array
item.
That's
this
thing.
This
whole
thing
is
an
array
item
I
can
tell
because
there's
this
little
leading
dash.
A
A
A
A
So
I'm
going
to
do
the
same
thing
of
clearing
out
any
of
the
defaults.
I
just
wrote
all
this
stuff
in,
but
I
just
wanted
to
make
clear
that
at
each
step
there
are
these
annotations,
but
when
we
see
the
resulting
annotation,
this
is
much
more
readable.
It's
just
which
document
needs
to
be
overlaid
and
what
is
the
contents,
each
map
item
being
merged
and
then
the
array
item
getting
appended
terrific.
A
Okay.
So
now,
let's
say
that
we've
learned
that
there's
a
new
version
of
nginx
available
and
the
upstream
team
hasn't
yet
adopted
it,
but
we
actually
want
to
take
advantage
of
some
of
those
features.
Let's
say
it's
like
nginx,
1.5,
1.19
or
something,
and
so
what
we
want
to
be
able
to
do
is
is
modify,
is
select
on
that
that
version
of
the
image.
So
how
would
we
do
that
in
an
overlay?
A
Okay,
so
we're
going
to
want
to
match
on
the
exact
same
document
we
did
before.
So
I'm
just
going
to
go
ahead
and
copy
this,
and
actually
all
the
way
down
to
the
containers,
and
I
might
be
tempted
to
actually
put
these
two
overlays
together
and
in
the
end,
maybe
I
would
but
for
now
just
for
clarity
and
simplicity,
I'm
going
to
keep
these
separate,
but
I
don't
have
to
be
creating
a
brand
new
document.
A
A
So,
let's
see
we've
got
three
overlays
being
applied
here
and
we
can
look
at
the
deployment.
We
see
that
the
containers
is
null
okay
right
because
all
along
the
way
we're
doing
this
overlay
match
merge
and
down.
Here.
The
value
of
a
node
in
a
yaml
document
is
null
if
it's
not
specified.
So
that's
what
that
is,
but
that's
not
what
we
want.
What
we
want
to
do
is
match
on
this
guy.
A
A
A
Okay,
and
so
let's
take
a
look
at
what
we've
got
here
so
now,
we've
got
in
containers.
We
have
one
two,
oh
three,
okay,
so
we
remember
that
without
any
explicit
configuration,
the
default
matching
for
an
array
item
is
to
not
match
on
any
item
in
the
array
and
to
append.
So
this
is
what
the
default
behavior
is.
What
we
want
to
do
is
actually
match
on
this
first
item.
A
A
A
We
do
a
little
bit
of
research
and
come
to
find
out.
It
looks
like
for
whatever
reason
the
upstream
team
has
made
a
commitment
to
specifying
which
host
port
the
nginx
container
is
going
to
listen
on
when
in
general
you
don't
need
to
specify
that
value.
Now
they
have
reasons
that
they
want
to
do
that,
but
those
aren't
our
reasons
that
actually
doesn't
apply
to
us.
So
what
we
want
to
do
is
get
rid
of
that
map
item
get
rid
of
that
host
port.
A
A
A
Locate
the
port
that
has
a
container
port
of
80
and
remove
its
corresponding
host
port.
Now,
there's
only
one
right
now,
but
ports
is
an
array,
so
we
want
to
be
careful.
We
want
to
just
find
the
one
that
has
the
this
is
the
container
port
and
then
remove
that
hose
board.
So,
let's,
let's
put
these
in
I'm
going
to
just
copy
both
these
down.
A
A
Okay,
so
I
don't
want
to
necessarily
include
this.
I
want
to
turn
this
into
the
matcher.
That's
the
I
that's
the
port
that
I
want
to
actually
match
on
so
I'll
use
our
trusty
subset
function
and
so
grab
our
container
port.
This
is
our
map
item
key
name,
and
this
is
the
value
it's
a
little
bit
here,
a
little
bit
of
space.
There
we
go
all
right
so
now
we
should
be
matching
on
the
container,
the
port
that
has
a
container
port
of
80.,
come
back
up
here,
oh
yeah.
A
A
A
A
So
let's
add
that
in
overlay
remote
great
okay,
so
we
come
up
here
and
oops
we've
got
a
serious
problem:
it's
not
just
removing
the
host
port
removed
everything
what's
going
on
here,
so
the
issue
here
has
to
do
with
how
annotations
find
the
node
that
they're
attached
to
what
I
mean
I
mean
here.
This
document
has
an
annotation
above
it
we've
been
thinking
about
that
annotation
describing
or
annotating
that
node
same
thing
here
with
this
matcher
on
this
array
item
and
what
we're
expecting
is
for
our
remove
to
be
matching
on
our
map
item.
A
But
it's
not,
let's
find
out
what
the
story
is
here
so
back
in
our
docs.
We
actually
have
a
really
nice
page
that
orients
us
on
yaml
structure
and
how
ytt
applies
annotations.
On
top
of
that,
so
this
document
has
two
parts.
The
first
part
is
details
about
the
terminology
and
the
structure
of
yaml
documents.
A
This
is
a
great
refresher,
even
if
you've
dealt
with
gamble
before
and
then
the
second
half
is
how
annotations
are
attached
to
that
structure
so
and
within
that
we
actually
have
a
called
out
section
on
exactly
this
topic:
how
an
annotation
finds
its
node,
which
node
does
an
annotation
match
on
it's
simple.
Thankfully,
there
are
two
rules.
A
The
first
is
if
the
annotation
has
a
node
on
its
left
like,
for
example,
right
here,
this
is
considered
an
annotation,
and
if
you
look
to
the
left
of
it,
there's
a
node,
then
this
annotation
is
considered
attached
to
this
node.
In
this
case,
this
is
a
map
item
and
this
expression
is
attached
to
that
map.
Item.
A
If
that
is
not
true,
if
there
is
no
node
to
the
left
of
the
annotation,
then
the
annotation
will
attach
to
whatever
the
next
node
is
that's
below
it.
So
an
example
back
here
is
in
this.
In
this
case,
this
overlay
replace
does
not
have
a
node
to
the
left
of
it,
there's
nothing
to
the
left
of
it,
and
so
it
also
attaches
to
that
same
map
item.
A
A
Okay,
so
let's
go:
let's
use
that
knowledge
and
fix
our
overlay,
so
here
right
now,
this
is
a
remove,
that's
being
applied
to
our
array
item
if
we
just
put
that
space
in
there
now.
This
remove
applies
to
the
hose
port
and
that's
exactly
what
we
see
the
container
port
remains,
but
the
hose
port
is
removed,
fantastic
and
now
these
containers
can
be
scheduled
on
any
node
all
right-
and
this
brings
us
to
our
final
scene
in
our
overall
story-
what's
happening
now
is
everything's
working
great.
A
But
from
time
to
time
we
found
that
some
parts
of
the
of
this
particular
service
is
a
little
bit
flaky
and
we
wish
that
we
had
the
ability
to
sometimes
be
able
to
turn
on
or
turn
up
debugging
on
our
app
here.
We
don't
always
want
it
on,
but
when
we
do,
we
want
all
of
our
components
to
go
into
a
debug
mode.
A
So
what
would
that
mean?
What
does
that
look
like?
Well,
it
means
different
things
for
different
pieces.
So,
for
example,
in
the
nginx
case,
the
way
to
enable
the
debug
mode
is
actually
to
run
the
debug
binary.
So
we
would
want
to
add
this
suffix
to
the
nginx
command.
So
that's
that's
that
piece,
but
we
wouldn't
want
to
turn
on
debugging
just
for
the
nginx.
We
actually
want
logging
to
be
turned
up
for
the
reda
server
as
well
in
here.
A
What
we
want
to
do
is
actually
there
there's
it's
using
the
default
command,
but
what
would
we
want
to
do
is
include
the
turn
up
the
logging
level,
and
so
we
would
want
to
add
the
command
key
and
in
here
include
the
redis,
the
binary
and
then
pat
and
then
pass
in
the
log
level
turn
up
the
log
level
to
debug
on
the
redis
server
itself.
So
we've
got
a
couple
edits
that
we
want
to
make
in
a
couple
different
places.
A
A
So
this
is
a
really
interesting
situation.
So
this
is
how
we
want
this
normally
to
occur.
The
this
the
configuration
for
redis
normally,
so
let's
go
ahead
and
get
started.
We're
going
to
take
these
one
piece
at
a
time.
What
we
want
to
do
first
is
add
that
suffix
to
the
nginx
debug
add
the
debug
suffix
to
the
command
all
right,
so
we're
going
to
do
yet.
Another
overlay.
A
We
want
to
be
able
to
find
and
edit
this
item
this
line,
and
I
guess
I
could
assume
that
it's
the
first
one,
but
it
would
be
safer.
If
I
matched
exactly
on
the
contents
here
so
delightfully,
we
can
continue
to
use
our
subset
matcher,
and
so,
let's
see
so
what
we're
going
to
do
is
we
want
to
match
on
a
command,
and
here
we
can
actually
just
put
in
the
exact
match.
A
So
this
is
good
for
an
exact
matcher
and
maybe
I'll
just
put
in
something
here
to
make
sure
that
this
is
working.
It's
not
yet.
Okay.
So,
let's
see
again
there's
a
lot
of
text
here.
I
start
from
the
back
and
work
my
way
in
so
in
line
12
we're
expecting
to
have
matched
one
but
matched
zero,
so
line
12.
A
A
We
want
to
rewrite
it,
so
let's
go
back
to
our
list
of
actions.
Again,
we've
been
playing
with
merge
and
append,
and
we
just
did
remove
now.
Here's
this
one
replace
and
what
replace
lets
you
do
is
not
just
replace
the
entire
contents,
but
actually
provide
a
an
expression,
a
function
that
takes
in
what
the
existing
value
is
and
what
value
you
have
in
your
overlay
and
you
can
combine
those
together
any
way
you'd
like
and
the
result
of
that
expression
is
what
gets
placed
in
the
final
output.
A
A
We
come
up
here
and
we
see
we've
successfully
edited
this.
We
can
put
any
expression
we
want
in
here.
We
could
have
prefixed
it
with
something
if
we'd
like
we
can
do
whatever
kind
of
edits
we
want.
So
this
is
a
really
powerful
way
of
editing
an
individual
item
with
an
overlay
all
right
so
far,
so
good.
So
now
our
nginx
is
in
debug
mode.
What
about
our
redis?
A
Well,
since
our
intention
is
to
enable
debugging,
we
can
actually
include
both
of
the
edits
for
our
containers
in
the
same
overlay.
So
I'm
going
to
actually,
unlike
what
I've
done
above,
is
keeping
these
separate
because
their
intentions
have
been
different.
I
want
to
show
I
want
to
illustrate
to
whoever's
reading
this
that
there's
two
edits.
There
is
the
change
to
the
nginx
and
the
change
to
the
radius.
So,
let's
start
matching
on
the
redis
container
over
here.
A
Let's
say
redis
server
and
then
we
want
to
turn
up
the
logging
level
to
debug
cool.
Let's
see
we
got
here:
okay,
wow,
so
line
16
on
the
command
expected
match
nodes
to
be
one,
but
with
zero.
What's
line
16
here
so
line
16
is
the
command
map
item.
A
So
if
I
look
to
see
what
I'm
overlaying
on,
there
is
no
command
map
item,
so
so
what
I
want
to
say
is
well:
if
it's
not
present,
then
just
then
just
add
it.
Okay
overlay
match
missing.
Okay,
right,
okay,
and
we
know
from
our
adventures
with
the
host
port
that
if
we
intend
this
annotation
to
decorate
this
map
item,
we
better
make
sure
that
there's
no
node
to
the
left
of
it.
A
A
A
A
It's
quite
possible
that
there
isn't
a
command
right
now
for
the
redis
container,
but
there
could
be-
and-
and
I
wouldn't
want
this
overlay
to
break
just
because
somebody
is
making
improvements
to
this
overlay.
A
And
when
we
have
that
now
we
see
where
there's
a
little
bit
of
a
trouble.
So
now
we've
got
not
a
great
command
line,
one
that's
not
going
to
work
well.
What
I
wished
was
happening
was
that
this
part
of
the
command
would
only
appear
if
it
if
it
isn't
already
in
the
list
and
that
the
overlay
would
add
just
this
item,
but
I'm
showing
a
future
possible
state,
so
this
command
won't
be
there
for
now.
I
just
want
to
be
tolerant
if
it
does
show
up
later.
A
A
So
what
I
want
to
do
is
include
a
custom
matcher.
What
do
I
mean
by
that?
Let's
go
back
to
our
documentation
for
the
overlay
match
and
we've
been
using
these
out
of
the
box
functions.
They're
super
useful.
You
can
see.
We've
got
a
lot
of
mileage
out
of
them,
but
now
we're
getting
into
a
zone
where
we
want
to
do
more,
and
this
is
where
the
custom
overlay
mattress
function.
So,
just
like
the
overlay
replace,
we
simply
need
to
provide
a
function,
and
this
one
the
signature
is
just
slightly
different.
A
This
signature
is
three
arguments.
The
first
that
our
function
will
receive
is
is
an
index
or
key,
so
as
the
overlay
is
attempting
to
match
on
different
items,
we're
actually
provided
if
it's
an
array
what
the
index
is
or
if
it's
a
map,
what
the
key
is
we're
currently
looking
at,
so
that
is
input
provided.
A
The
next
is
what
is
the
total
value
of
the
existing
item?
So
that's
what
left
is
and
then
the
right
is
whatever
we
are
annotating
over.
This
is
the
value
inside
of
our
overlay,
on
which
the
matcher
is
annotating,
and
it
should
provide
it's
a
predicate.
It
should
describe
whether
or
not
we
match
so
the
expression
for
this
function
should
decide
whether
or
not
we're
matching
okay.
So,
armed
with
that
we're
going
to
write
another
lambda
function
and
it's
going
to
take
an
index.
A
The
left
side,
that's
an
l
and
the
right
side
going
to
keep
this
short.
So
it's
a
little
bit
easier
to
read
on
this
smaller
space,
so
I'm
not
really
going
to
use
the
index.
What
I
care
about
is
that
if
there
is
I'm
going
to
try
and
match
on
the
existing
presence
of
the
reddish
server
command,
so
what
I'll
say
is
well
if
the
left
now
that's
a
string
and
I
deliberately
try
to
make
it
so
that
they
aren't
going
to
match
exactly.
A
A
So
here,
when
you're
doing
string
matching,
you
can
actually
use
some
built-in
functions
that
starlock
provides
on
string
values
here.
If
this
will
match,
if
the
metadata
name
has
the
server
suffix
all
right,
but
for
us
what
I
want
to
do
is
look
at
the
string
functions
that
are
available
on
strings.
So
I
follow
that
link,
and
these
are
all
of
the
built-ins
that
are
available
on
strings.
A
A
A
So
so
here
we
want
to
say
in
within
what's
present,
if
we
can
find
sorry
the
value
being
annotated
here,
redis
server,
if
that
is
greater
than
minus
one,
that
means
that
we've
matched
now.