Skip to content

Conversation

@jjqq2013
Copy link

@jjqq2013 jjqq2013 commented Jul 8, 2025

Just fix typos, add some explanation about execution order of Cloud-init files, steps, and substeps, which are not that obvious to users.

@jjqq2013 jjqq2013 requested a review from a team as a code owner July 8, 2025 02:36
@jjqq2013 jjqq2013 force-pushed the james-doc branch 6 times, most recently from 1b965ae to 1e6610d Compare July 8, 2025 04:53
@jjqq2013 jjqq2013 changed the title Fix typos, add docs about execution order of Cloud-init stages and steps Fix typos, add docs about execution order of Cloud-init files, steps, and substeps Jul 8, 2025
@jjqq2013 jjqq2013 changed the title Fix typos, add docs about execution order of Cloud-init files, steps, and substeps Fix typos. Add docs about execution order of Cloud-init files, steps, and substeps Jul 8, 2025
@jjqq2013 jjqq2013 changed the title Fix typos. Add docs about execution order of Cloud-init files, steps, and substeps Add docs about execution order of Cloud-init files, steps, and substeps Jul 22, 2025
Comment on lines 91 to 165
- The execution order of multiple `substeps` (such as `files`, `commands`, `environment` etc.) within a single `step` is not guaranteed.
Therefore, when you have multiple `substeps` that related to each other, please do not define them in a single `step`.
Instead, you can split the `substeps` into multiple `steps` which are ensured to be executed by the definition order.
- The name of `steps` and output of `substeps` will be output to system journal log which can be viewed by the command `journalctl -u 'elemental*'`.
- It is highly recommended to declare the `name` property of *steps*, so that it will be easier to investigate the output of `journalctl -u 'elemental*'` by the name.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The wording here is pretty confusing.
In other places in the documentation, it's referred to as stage and action:

stages:
  fs:  # <-- this is a "stage"
    - name: "foobar"  # <-- this is an "action"
      command: echo foobar

Copy link
Author

@jjqq2013 jjqq2013 Aug 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the fs is obviously an stage.
The properties in it seems is called as "steps" in other documents, instead of action, e.g., https://rancher.github.io/elemental-toolkit/docs/customizing/stages/
image

And https://rancher.github.io/elemental-toolkit/docs/reference/cloud_init/
image

How do you think?

Should we change steps to actions?

Copy link
Author

@jjqq2013 jjqq2013 Aug 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The point I'd like to clarify is the substeps which is not explicitly described anywhere.

stages:
  fs:  # <-- this is a "stage"
    - name: "foobar"  # <-- this is an "step title"
      commands:               #  <-- I'd like to call this as a substep. 
        - echo foobar
        - command2
      files:                          #  <-- I'd like to call this as a substep. 
         - path: ..
            content: ...
         - path: ..
            content: ...

It is not clear about if the commands are executed before files or reverse.

(But of course inside the same substep, such as commands, it is an array, each item in it is executed by the definition order).

- During upgrades, installation, deployments , and resets

Cloud-init files in `/system/oem`, `/oem` and `/usr/local/oem` are applied in 5 different phases: `boot`, `network`, `fs`, `initramfs` and `reconcile`. All the available cloud-init keywords can be used in each stage. Additionally, it's possible also to hook before or after a stage has run, each one has a specific stage which is possible to run steps: `boot.after`, `network.before`, `fs.after` etc.
Cloud-init files in `/system/oem`, `/oem`, `/usr/local/oem`, and kernel boot args are applied in 5 different phases: `boot`, `network`, `fs`, `initramfs` and `reconcile`. All the available cloud-init keywords can be used in each stage. Additionally, it's possible also to hook before or after a stage has run, each one has a specific stage which is possible to run steps: `boot.after`, `network.before`, `fs.after` etc.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reconcile phase is special, because it's executed repeatedly on a timer. The other phases are executed during system boot.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for pointing the reconcile phase, but that is not my modification.
My modification is only to add the kernel boot args.

image

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW, here you can see, the term phases is used for stages such as fs. Should we unify them? But probably it is not that confusing.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would agree to change phases to stages in the above examples 👍

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@frelon Changed to stages, but only for above case.

Each cloud-config file is loaded and executed only at the appropriate stage, this allows further components to emit their own stages at the desired time.

_Note_:
- The execution order of multiple `substeps` (such as `files`, `commands`, `environment` etc.) within a single `step` is not guaranteed.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I can tell, this is not true. The execution order within a stage should be as-listed in each file and each group of actions in each file should be executed according to the alphabetical order of filenames.

Copy link
Author

@jjqq2013 jjqq2013 Aug 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is what I'd like to clarify.
The order is not the order defined in the yaml, this is mainly because the definition order of properties in yaml(or json) is not respected.

stages:
  fs:
    - name: test
      environment_file: /tmp/env_file1
      environment:
        ENV1: this is ENV1
      files:
        - path: /tmp/file1
          content: "this is file1\n"
      directories:
        - path: /tmp/dir1
      users:
        user1:
            passwd: password
      commands:
        - |
          bash -x >> /tmp/log 2>&1 <<'EOF'
          ls -lFd /tmp/env_file1
          printenv ENV1
          ls -lFd /tmp/file1
          ls -lFd /tmp/dir1
          id user1
          EOF

You might expect that when the commands get executed, all things defined above it has been executed, such as the user1 has been created.
But it is not. As of now, the output (/tmp/log) is:

+ ls -lFd /tmp/env_file1
ls: cannot access '/tmp/env_file1': No such file or directory
+ printenv ENV1
this is ENV1
+ ls -lFd /tmp/file1
---------- 1 root root 14 Aug  6 07:13 /tmp/file1
+ ls -lFd /tmp/dir1
d--------- 2 root root 40 Aug  6 07:13 /tmp/dir1/
+ id user1
id: ‘user1’: no such user

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi!

The execution order of steps in a stage is defined here. This means that the files(EnsureFiles plugin) is always executed before the commands plugin for example.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fferrann @m-ildefons Thanks for pointing out the ref. Yes, I know where is the definition, but most users don't have time to check source code for such things. And there is no obvious logical reason that why it is implemented in such a way, it is just happened to be that order. So I think the document should explicitly tell users about the order is not like what they might think.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The order might change in the future, such as when adding a new substeps, then where is should be put? and who is going to determine the order? Who can know the order just by the substep name without thinking deeply or checking source code?

Comment on lines 92 to 93
Therefore, when you have multiple `substeps` that related to each other, please do not define them in a single `step`.
Instead, you can split the `substeps` into multiple `steps` which are ensured to be executed by the definition order.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO this is pretty hard to understand. An example would help.

Copy link
Author

@jjqq2013 jjqq2013 Aug 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jjqq2013
Copy link
Author

jjqq2013 commented Aug 6, 2025

@m-ildefons Thank you so much for taking a look into this. I will modify the document. Your comments are very helpful.

@jjqq2013 jjqq2013 force-pushed the james-doc branch 3 times, most recently from 0fa17c0 to 9f21fa8 Compare August 6, 2025 07:23
@jjqq2013
Copy link
Author

jjqq2013 commented Aug 6, 2025

I have updated some description.

```

You might expect that when the `commands` get executed, all things defined above it has been executed, such as the user1 has been created.
But it is not. As of now, the output (/tmp/log) is:
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mark

Copy link
Contributor

@frelon frelon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some comments, also I would remove any mention of substeps, yip works using stages and steps.

EOF
```

You might expect that when the `commands` get executed, all things defined above it has been executed, such as the user1 has been created.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As described before the execution ordering is specified when loading the plugins in

executor.WithPlugins(

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me add the reference to the document. Welcome to correct me.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

```

The internal order is depending on the implementation, see https://github.com/rancher/elemental-toolkit/blob/d8450e01b9119b76670421880070d2cc7fa5f936/pkg/cloudinit/cloudinit.go#L52.
You can see that the `plugins.User` is behind `plugins.Commands`.
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mark

@jjqq2013 jjqq2013 force-pushed the james-doc branch 3 times, most recently from b58c393 to 05167d0 Compare August 6, 2025 07:49
ls -lFd /tmp/file1
ls -lFd /tmp/dir1
id user1
EOF
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mark. See above "step1" and "step2". Multiple steps defined in a stage will be executed by the definition order,
but inside each step, there are multiple plugin in it, such as files, 'commands`, what should we call them? @frelon

@jjqq2013
Copy link
Author

jjqq2013 commented Aug 6, 2025

Some comments, also I would remove any mention of substeps, yip works using stages and steps.

@frelon Welcome to give it a better name. What would you call the properties under same step? Could you please check https://github.com/rancher/elemental-toolkit/pull/2294/files#r2256228693 ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants