Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stages hooks vibes #330

Open
wants to merge 6 commits into
base: edge
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
## {{ UNRELEASED_VERSION }} - [{{ UNRELEASED_DATE }}]({{ UNRELEASED_LINK }})

* Added `pre-` and `post-` as syntactical sugar for `L337` service `group` override syntax
* Fixed bug causing `v4` services to be unnecessarily rebuilt on non-rebuildy commands eg `lando start`

## v3.24.0-beta.12 - [January 24, 2025](https://github.com/lando/core/releases/tag/v3.24.0-beta.12)

* Merged in improvements from `@lando/[email protected]`
Expand Down
51 changes: 34 additions & 17 deletions components/l337-v4.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const toPosixPath = require('../utils/to-posix-path');
class L337ServiceV4 extends EventEmitter {
#app
#data
#dgroups
#lando

static debug = require('debug')('@lando/l337-service-v4');
Expand All @@ -49,13 +50,15 @@ class L337ServiceV4 extends EventEmitter {
groups: {
context: {
description: 'A group for adding and copying sources to the image',
weight: 0,
stage: 'image',
user: 'root',
weight: 0,
},
default: {
description: 'A default general purpose build group around which other groups can be added',
weight: 1000,
stage: 'image',
user: 'root',
weight: 1000,
},
},
image: undefined,
Expand All @@ -69,7 +72,6 @@ class L337ServiceV4 extends EventEmitter {
},
sources: [],
stages: {
default: 'image',
image: 'Instructions to help generate an image',
},
states: {
Expand Down Expand Up @@ -151,9 +153,11 @@ class L337ServiceV4 extends EventEmitter {
fs.mkdirSync(this.tmpdir, {recursive: true});

// initialize our private data
// note that you cannot override the default|context groups
this.#app = app;
this.#dgroups = {groups: this.#init().groups ?? {}};
this.#lando = lando;
this.#data = merge(this.#init(), {groups}, {stages}, {states}, {volumes: Object.keys(tlvolumes)});
this.#data = merge(this.#init(), {groups}, {stages}, {states}, {volumes: Object.keys(tlvolumes)}, this.#dgroups);

// rework info based on whatever is passed in
this.info = merge({}, {state: states}, {primary, service: id, type}, info);
Expand Down Expand Up @@ -191,6 +195,11 @@ class L337ServiceV4 extends EventEmitter {
// debug
this.debug('%o autoset appmount to %o, did not select %o', this.id, this.appMount, appMounts);
}

// if the image is already built then lets set the tag and stuff here
if (this.info?.state?.IMAGE === 'BUILT' && this.tag) {
this.addComposeData({services: {[this.id]: {image: this.tag}}});
}
}

// passed in build args that can be used
Expand Down Expand Up @@ -346,11 +355,11 @@ class L337ServiceV4 extends EventEmitter {
}

// merge in
this.#data.groups = merge({}, this.#data.groups, {[group.id || group.name]: {
description: group.description || `Build group: ${group.id || group.name}`,
weight: group.weight || this.#data.groups.default.weight || 1000,
stage: group.stage || this.#data.stages.default || 'image',
user: group.user || 'root',
this.#data.groups = merge({}, this.#data.groups, {[group.id ?? group.name]: {
description: group.description ?? `Build group: ${group.id ?? group.name}`,
weight: group.weight ?? this.#data.groups.default.weight ?? 1000,
stage: group.stage ?? this.#data.groups.default.stage ?? 'image',
user: group.user ?? this.#data.groups.default.user ?? 'root',
}});

this.debug('%o added build group %o', this.id, group);
Expand All @@ -361,12 +370,14 @@ class L337ServiceV4 extends EventEmitter {
// this handles our changes to docker-composes "image" key
// @TODO: helper methods to add particular parts of build data eg image, files, steps, groups, etc
addImageData(data) {
// make sure data is in object format if its a string then we assume it sets the "imagefile" value
if (typeof data === 'string') data = {imagefile: data};
// make sure data is in object format if its stringy then we assume it sets the "imagefile" value
if (typeof data === 'string' || data?.constructor?.name === 'ImportString') data = {imagefile: data};
// map dockerfile key to image key if it is set and imagefile isnt
if (!data.imagefile && data.dockerfile) data.imagefile = data.dockerfile;

// now pass the imagefile stuff into image parsing
this.setBaseImage(data.imagefile);

// if the imageInstructions include COPY/ADD then make sure we are adding the dockerfile context directly as a
// source so those instructions work
// @NOTE: we are not adding a "context" because if this passes we have the instructions already and just need to make
Expand Down Expand Up @@ -436,11 +447,12 @@ class L337ServiceV4 extends EventEmitter {

// we should have stnadardized groups at this point so we can rebase on defaults as
step = merge({},
{stage: this.#data.stages.default},
{stage: this.#data.groups.default.stage},
{weight: this.#data.groups.default.weight, user: this.#data.groups.default.user},
this.#data.groups[step.group],
step,
);

// now lets modify the weight by the offset if we have one
if (step.offset && Number(step.offset)) step.weight = step.weight + step.offset;
// and finally lets rewrite the group for better instruction grouping
Expand Down Expand Up @@ -539,6 +551,7 @@ class L337ServiceV4 extends EventEmitter {
// add the final compose data with the updated image tag on success
// @NOTE: ideally its sufficient for this to happen ONLY here but in v3 its not
this.addComposeData({services: {[context.id]: {image: context.tag}}});

// set the image stuff into the info
this.info = {image: imagefile, state: {IMAGE: 'BUILT'}, tag: context.tag};
this.debug('image %o built successfully from %o', context.id, imagefile);
Expand Down Expand Up @@ -662,10 +675,14 @@ class L337ServiceV4 extends EventEmitter {

// gets group overrides or returns false if there are none
getGroupOverrides(group) {
// break the group into parts
const parts = group.replace(`${this.getOverrideGroup(group)}`, '').split('-');
// there will always be a leading '' element so dump it
parts.shift();
// break the group into parts and remove empty strings
const parts = group.replace(`${this.getOverrideGroup(group)}`, '').split('-').filter(part => part && part !== '');

// translate pre|post syntax
if (['pre', 'post'].includes(parts[0])) {
parts[0] = parts[0] === 'pre' ? 'before' : 'after';
if (parts.length === 1) parts.push('1');
}

// if we have nothing then lets return false at this point
if (parts.length === 0) return false;
Expand Down Expand Up @@ -697,7 +714,7 @@ class L337ServiceV4 extends EventEmitter {
// this should ensure we end up with an ordered by closest match list
const candidates = Object.keys(this.#data.groups)
.sort((a, b) => b.length - a.length)
.filter(group => data.startsWith(group));
.filter(group => data.startsWith(group) || data.startsWith(`pre-${group}`) || data.startsWith(`post-${group}`));

// if there is a closest match that is not the group itself then its an override otherwise fise
return candidates.length > 0 && candidates[0] !== data ? candidates[0] : false;
Expand Down
13 changes: 12 additions & 1 deletion docs/services/l337.md
Original file line number Diff line number Diff line change
Expand Up @@ -513,14 +513,25 @@ While you _can_ use `COPY` and `ADD` instructions here we recommend you use [`co

#### Override syntax

The group override syntax is flexible as long as the parent group is first. For example the following overrides are equivalent:
You can also override _any_ group with a `before|after`, `user` and `offset` to gain more flexible on _when_ and _who_ runs a given step. The group override syntax is flexible as long as the parent group is first.

All the group overrides in the example below are equivalent. Any step using them will run as the `root` user at `+2` weight (eg after) to the weight provided by the `system` group.

```bash
system-2
system-2-after
system-root-after-2
system-2-after-root
system-root-2-after
post-system-2
```

Similarly, all of the below run as the `nginx` user but at `-2` weight (eg before) to the `system` group.

```bash
system-2-before-nginx
system-nginx-before-2
pre-system-2-nginx
```

That said, we like the `GROUP-OFFSET-DIRECTION-USER` format. ;)
Expand Down
21 changes: 21 additions & 0 deletions examples/l337/.lando.yml
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,14 @@ services:
# direct group usage
- instructions: RUN echo "${LANDO_IMAGE_USER}-${LANDO_IMAGE_GROUP}-$(whoami)" >> /tmp/groups
group: "val-jean"
- instructions: RUN echo "${LANDO_IMAGE_USER}-${LANDO_IMAGE_GROUP}-$(whoami)" >> /tmp/groups
group: "pre-val-jean"
- instructions: RUN echo "${LANDO_IMAGE_USER}-${LANDO_IMAGE_GROUP}-$(whoami)" >> /tmp/groups
group: "post-val-jean"
- instructions: RUN echo "${LANDO_IMAGE_USER}-${LANDO_IMAGE_GROUP}-$(whoami)" >> /tmp/groups
group: "pre-val-jean-4"
- instructions: RUN echo "${LANDO_IMAGE_USER}-${LANDO_IMAGE_GROUP}-$(whoami)" >> /tmp/groups
group: "post-val-jean-5"
- instructions: RUN echo "${LANDO_IMAGE_USER}-${LANDO_IMAGE_GROUP}-$(whoami)" >> /tmp/groups
group: "user"
- instructions: RUN echo "${LANDO_IMAGE_USER}-${LANDO_IMAGE_GROUP}-$(whoami)" >> /tmp/groups
Expand Down Expand Up @@ -398,6 +406,19 @@ services:
- instructions: RUN echo "first" >> /stuff
weight: 1

import:
api: 4
type: l337
image:
imagefile: !import Dockerfile
steps:
- instructions: !import instructions/Instructions1
weight: 1
- instructions: !import instructions/Instructions2
weight: 2
- instructions: !import instructions/Instructions3
weight: 3

networks:
my-network:
volumes:
Expand Down
57 changes: 34 additions & 23 deletions examples/l337/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ lando info --service image-5 | grep tag: | grep "lando/l337\-" | grep "\-image-5
lando info --service image-6 | grep tag: | grep "lando/l337\-" | grep "\-image-6:latest"

# should use web as the primary service for tooling and events
lando ssh --command "env" | grep SERVICE | grep web
lando exec web -- env | grep SERVICE | grep web
lando env | grep SERVICE | grep web

# should use the user as the default exec user
Expand Down Expand Up @@ -122,21 +122,21 @@ lando ssh --service image-3 --command "stat /file1"

# should run in working_dir if appMount is not set
lando pwd --service db | grep /tmp
lando ssh --service db --command "pwd" | grep /tmp
lando exec db -- pwd | grep /tmp
cd folder
lando pwd --service db | grep -w /tmp
lando ssh --service db --command "pwd" | grep /tmp
lando exec db -- pwd | grep /tmp
cd ..

# should run in image working_dir as fallback
lando pwd --service image-1 | grep -w /
lando ssh --service image-1 --command "pwd" | grep -w /
lando exec image-1 -- pwd | grep -w /
lando pwd --service image-6 | grep /usr/share/nginx/html
lando ssh --service image-6 --command "pwd" | grep /usr/share/nginx/html
lando exec image-6 -- pwd | grep /usr/share/nginx/html

# should correctly mount read-only volumes
lando ssh --command "test -r /file-ro"
lando ssh --command "test -w /file-ro" || echo $? | grep 1
lando exec web -- test -r /file-ro
lando exec web -- test -w /file-ro || echo $? | grep 1

# should handle all context options correctly
lando stat /folder
Expand Down Expand Up @@ -178,12 +178,16 @@ lando groups | sed -n '11p' | grep root-default-1000-root-root
lando groups | sed -n '12p' | grep root-default-1000-root-root
lando groups | sed -n '13p' | grep nginx-user-10000-nginx-nginx
lando groups | sed -n '14p' | grep nginx-val-jean-24591-nginx-nginx
lando groups | sed -n '15p' | grep root-val-jean-24601-root-root
lando groups | sed -n '16p' | grep root-val-jean-24603-root-root
lando groups | sed -n '17p' | grep root-val-jean-24604-root-root
lando groups | sed -n '18p' | grep nginx-val-jean-24605-nginx-nginx
lando groups | sed -n '19p' | grep nginx-val-jean-24606-nginx-nginx
lando groups | sed -n '20p' | grep root-val-jean-24701-root-root
lando groups | sed -n '15p' | grep root-val-jean-24597-root-root
lando groups | sed -n '16p' | grep root-val-jean-24600-root-root
lando groups | sed -n '17p' | grep root-val-jean-24601-root-root
lando groups | sed -n '18p' | grep root-val-jean-24602-root-root
lando groups | sed -n '19p' | grep root-val-jean-24603-root-root
lando groups | sed -n '20p' | grep root-val-jean-24604-root-root
lando groups | sed -n '21p' | grep nginx-val-jean-24605-nginx-nginx
lando groups | sed -n '22p' | grep root-val-jean-24606-root-root
lando groups | sed -n '23p' | grep nginx-val-jean-24606-nginx-nginx
lando groups | sed -n '24p' | grep root-val-jean-24701-root-root

# should run build steps as the correct user
lando groups | sed -n '1p' | grep root-default--99999999-root-root
Expand All @@ -200,25 +204,32 @@ lando groups | sed -n '11p' | grep root-default-1000-root-root
lando groups | sed -n '12p' | grep root-default-1000-root-root
lando groups | sed -n '13p' | grep nginx-user-10000-nginx-nginx
lando groups | sed -n '14p' | grep nginx-val-jean-24591-nginx-nginx
lando groups | sed -n '15p' | grep root-val-jean-24601-root-root
lando groups | sed -n '16p' | grep root-val-jean-24603-root-root
lando groups | sed -n '17p' | grep root-val-jean-24604-root-root
lando groups | sed -n '18p' | grep nginx-val-jean-24605-nginx-nginx
lando groups | sed -n '19p' | grep nginx-val-jean-24606-nginx-nginx
lando groups | sed -n '20p' | grep root-val-jean-24701-root-root
lando groups | sed -n '15p' | grep root-val-jean-24597-root-root
lando groups | sed -n '16p' | grep root-val-jean-24600-root-root
lando groups | sed -n '17p' | grep root-val-jean-24601-root-root
lando groups | sed -n '18p' | grep root-val-jean-24602-root-root
lando groups | sed -n '19p' | grep root-val-jean-24603-root-root
lando groups | sed -n '20p' | grep root-val-jean-24604-root-root
lando groups | sed -n '21p' | grep nginx-val-jean-24605-nginx-nginx
lando groups | sed -n '22p' | grep root-val-jean-24606-root-root
lando groups | sed -n '23p' | grep nginx-val-jean-24606-nginx-nginx
lando groups | sed -n '24p' | grep root-val-jean-24701-root-root

# Should run steps in all allowed formats
lando env --service steps-1 | grep VIBES | grep RISING
lando env --service steps-1 | grep KIRK | grep wesley
lando env --service steps-1 | grep SPOCK | grep peck
lando env --service import | grep LANDO_STRINGY_IMPORT_INSTRUCTIONS_1 | grep 1
lando env --service import | grep LANDO_STRINGY_IMPORT_INSTRUCTIONS_2 | grep 1
lando env --service import | grep LANDO_STRINGY_IMPORT_INSTRUCTIONS_3 | grep 1

# Should run unknown groups as the default group
lando ssh --service steps-1 --command "cat /tmp/val-jean-group" | grep default-1000-root
lando exec steps-1 -- cat /tmp/val-jean-group | grep default-1000-root

# Should order detached groups by weight
lando ssh --service steps-1 --command "cat /stuff" | sed -n '1p' | grep first
lando ssh --service steps-1 --command "cat /stuff" | sed -n '2p' | grep middle
lando ssh --service steps-1 --command "cat /stuff" | sed -n '3p' | grep last
lando exec steps-1 -- cat /stuff | sed -n '1p' | grep first
lando exec steps-1 -- cat /stuff | sed -n '2p' | grep middle
lando exec steps-1 -- cat /stuff | sed -n '3p' | grep last
```

## Destroy tests
Expand Down
2 changes: 2 additions & 0 deletions examples/l337/instructions/Instructions1
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ENV MARIADB_ALLOW_EMPTY_ROOT_PASSWORD=1
ENV LANDO_STRINGY_IMPORT_INSTRUCTIONS_1=1
1 change: 1 addition & 0 deletions examples/l337/instructions/Instructions2
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ENV LANDO_STRINGY_IMPORT_INSTRUCTIONS_2=1
1 change: 1 addition & 0 deletions examples/l337/instructions/Instructions3
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ENV LANDO_STRINGY_IMPORT_INSTRUCTIONS_3=1
1 change: 1 addition & 0 deletions hooks/app-run-v4-build-image.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ module.exports = async (app, lando) => {
const services = _(app.v4.services)
.filter(service => _.includes(buildV4Services, service.id))
.filter(service => typeof service.buildImage === 'function')
.filter(service => service?.info?.state?.IMAGE !== 'BUILT')
.value();

app.log.debug('going to build v4 images', services.map(service => service.id));
Expand Down
Loading