Search code examples
pythonlinuxyamljinja2salt-project

How to require a dynamically created salt state from within a loop that is also dynamically creating salt states?


Here is what I am trying to accomplish.

I have a salt state that manages users and groups in linux, /etc/skel templates, and will later manage many other user related templates.

In short:

Some states are created from reading a pillar with users and properties in a for loop.

Some states are created from reading a pillar with groups and properties.

Groups will exist that are the the primary group for a user, not all groups will have a primary user, and all created users will have a primary group created that is named after the user. It seems that the group has to be created with salt prior to creating the user. So, for each user state, where the state is created by the loop, and the user is created by that state, needs to require a corresponding group. However the group states don't statically exist they are also created dynamically from the group pillar. So, salt doesn't necessarily render every state in the same order each time as it does an alphabetic sort, but the order is determined after all the requisites are solved. (BTW. I tried to keep this summary of the sort short and not get down a rabbit hole here on salt render topics.)

I think the issue I am having is that the group state has not been created at the time the user states are created.

I have posted below the state with the require configuration which generates the error. When the requirement exist it does not create the user but does create the group, when the requirement is removed, it created the group and the user.

If I remove the require line, I currently get my expected result, but not sure that I would always get the expected result long term as this grows.

Also, am very interested in finding a way to require something from a dynamically created state within another dynamically created stated.

Any ideas here to revise this to solve that issue would be appreciated as always here :)

Here is the state file:

/etc/skel:
  file.directory:
    - name: /etc/skel
    - user: root
    - group: root
    - dir_mode: 755
/etc/skel/.bash_logout:
  file.managed:
    - name: /etc/skel/.bash_logout
    - user: root
    - group: root
    - mode: 644
    - source: salt://user_management/templates/etc/skel/bash_logout.sls
/etc/skel/.bash_profile:
  file.managed:
    - name: /etc/skel/.bash_profile
    - user: root
    - group: root
    - mode: 644
    - source: salt://user_management/templates/etc/skel/bash_profile.sls
/etc/skel/.bashrc:
  file.managed:
    - name: /etc/skel/.bashrc
    - user: root
    - group: root
    - mode: 644
    - source: salt://user_management/templates/etc/skel/bashrc.sls
{% for group in pillar['user_management']['groups'] %}
{{- group }}:
  group.present:
    - name: "{{ pillar['user_management']['groups'][group]['name'] }}"
    - gid: "{{ pillar['user_management']['groups'][group]['gid'] }}"
    - system: "{{ pillar['user_management']['groups'][group]['system'] }}"
  {%- if pillar['user_management']['groups'][group]['addusers'] %}
    - addusers:
    {%- for add_user_name in pillar['user_management']['groups'][group]['addusers'] %}
      - {{ add_user_name }}
    {%- endfor %}
  {%- endif %}
  {%- if pillar['user_management']['groups'][group]['delusers'] %}
    - delusers:
    {%- for del_user_name in pillar['user_management']['groups'][group]['delusers'] %}
      - {{ del_user_name }}
    {%- endfor %}
  {%- endif %}
  {%- if pillar['user_management']['groups'][group]['members'] %}
    - members:
    {%- for member_name in pillar['user_management']['groups'][user]['members'] %}
      - {{ member_name }}
    {%- endfor %}
  {%- endif %}
{% endfor %}
{% for user in pillar['user_management']['users'] %}
{{- user }}:
  user.present:
    - name: "{{ pillar['user_management']['users'][user]['name'] }}"
    - uid: "{{ pillar['user_management']['users'][user]['uid'] }}"
    - gid: "{{ pillar['user_management']['users'][user]['gid'] }}"
    - gid_from_name: "{{ pillar['user_management']['users'][user]['gid_from_name'] }}"
  {%- if pillar['user_management']['users'][user]['groups'] %}
    - groups:
    {%- for group_name in pillar['user_management']['users'][user]['groups'] %}
      - {{ group_name }}
    {%- endfor %}
  {%- endif %}
  {%- if pillar['user_management']['users'][user]['optional_groups'] %}
    - optional_groups:
    {%- for optional_group_name in pillar['user_management']['users'][user]['optional_groups'] %}
      - {{ optional_group_name }}
    {%- endfor %}
  {%- endif %}
  {%- if pillar['user_management']['users'][user]['remove_groups'] %}
    - remove_groups:
    {%- for remove_group_name in pillar['user_management']['users'][user]['remove_groups'] %}
      - {{ remove_group_name }}
    {%- endfor %}
  {%- endif %}
    - home: "{{ pillar['user_management']['users'][user]['home'] }}"
    - createhome: "{{ pillar['user_management']['users'][user]['createhome'] }}"
    - password: "{{ pillar['user_management']['users'][user]['password'] }}"
    - enforce_password: "{{ pillar['user_management']['users'][user]['enforce_password'] }}"
    - empty_password: "{{ pillar['user_management']['users'][user]['empty_password'] }}"
    - shell: "{{ pillar['user_management']['users'][user]['shell'] }}"
    - unique: "{{ pillar['user_management']['users'][user]['unique'] }}"
    - system: "{{ pillar['user_management']['users'][user]['system'] }}"
    - fullname: "{{ pillar['user_management']['users'][user]['fullname'] }}"
    - require:
      - group: {{ user|replace("user", "group") }}
{% endfor %}

Here is the user pillar file:

user_management:
  users:
    user_mdresden:
      name: mdresden
      uid: 10000
      gid: 10000
      gid_from_name: True
      groups:
        - wheel
      optional_groups:
        - users
      remove_groups:
        # - list
      home: /home/mdresden
      createhome: True
      password: '$6$wBMXk1u6Jxapb5GR$o4YckBYhVjZZ28vyOkcPwBLMH2tcgWAPqdqzLLOGGY5DCM1aaz/rNfnjpMdcmE4GFt/5dzwu8z3YXViptLTMT/'
      enforce_password: True
      empty_password: False
      shell: "/bin/bash"
      unique: True
      system: False
      fullname: "Matthew Dresden"
    user_csunderarajulu:
      name: csunderarajulu
      uid: 10001
      gid: 10001
      gid_from_name: True
      groups:
        # - list
      optional_groups:
        - users
      remove_groups:
        # - list
      home: /home/csunderarajulu
      createhome: True
      password: '$6$wBMXk1u6Jxapb5GR$o4YckBYhVjZZ28vyOkcPwBLMH2tcgWAPqdqzLLOGGY5DCM1aaz/rNfnjpMdcmE4GFt/5dzwu8z3YXViptLTMT/'
      enforce_password: True
      empty_password: False
      shell: "/bin/bash"
      unique: True
      system: False
      fullname: "Chandrasekaran Sunderarajulu"

Here is the group pillar file:

user_management:
  groups:
    group_mdresden:
      name: mdresden
      gid: 10000
      system: False
      addusers:
        # - list
        # - list
      delusers:
        # - list
        # - list
      members:
    group_csunderarajulu:
      name: csunderarajulu
      gid: 10001
      system: False
      addusers:
        # - list
        # - list
      delusers:
        # - list
        # - list
      members:

The error only seems to occur on a real run, not with test enabled. Here is the error for the users:

user_|-user_csunderarajulu_|-csunderarajulu_|-present:
    ----------
    __run_num__:
        7
    __sls__:
        user_management.users.manage
    changes:
        ----------
    comment:
        One or more requisite failed: user_management.users.manage.group_csunderarajulu
    result:
        False
user_|-user_mdresden_|-mdresden_|-present:
    ----------
    __run_num__:
        6
    __sls__:
        user_management.users.manage
    changes:
        ----------
    comment:
        One or more requisite failed: user_management.users.manage.group_mdresden
    result:
        False

Here is the result when I remove the requirement:

user_|-user_csunderarajulu_|-csunderarajulu_|-present:
    ----------
    __run_num__:
        7
    changes:
        ----------
        fullname:
            Chandrasekaran Sunderarajulu
        gid:
            10001
        groups:
            - csunderarajulu
            - users
        home:
            /home/csunderarajulu
        homephone:
        name:
            csunderarajulu
        passwd:
            x
        roomnumber:
        shell:
            /bin/bash
        uid:
            10001
        workphone:
    comment:
        New user csunderarajulu created
    duration:
        106.136
    name:
        csunderarajulu
    result:
        True
    start_time:
        20:55:32.687433
user_|-user_mdresden_|-mdresden_|-present:
    ----------
    __run_num__:
        6
    changes:
        ----------
        fullname:
            Matthew Dresden
        gid:
            10000
        groups:
            - mdresden
            - users
            - wheel
        home:
            /home/mdresden
        homephone:
        name:
            mdresden
        passwd:
            x
        roomnumber:
        shell:
            /bin/bash
        uid:
            10000
        workphone:
    comment:
        New user mdresden created
    duration:
        153.671
    name:
        mdresden
    result:
        True
    start_time:
        20:55:32.532969

While the group is created seemingly successfully, the output from the the group create also shows an error.

Here is the output for the group that shows the error:

group_|-group_csunderarajulu_|-csunderarajulu_|-present:
        ----------
        __run_num__:
            5
        changes:
            ----------
            Failed:
                ----------
                gid:
                    10001
        comment:
            Group {0} has been created but, some changes could not be applied
        duration:
            34.491
        name:
            csunderarajulu
        result:
            False
        start_time:
            13:40:14.615013
    group_|-group_mdresden_|-mdresden_|-present:
        ----------
        __run_num__:
            4
        changes:
            ----------
            Failed:
                ----------
                gid:
                    10000
        comment:
            Group {0} has been created but, some changes could not be applied
        duration:
            168.642
        name:
            mdresden
        result:
            False
        start_time:
            13:40:14.445528

Here is the output of: salt-call --local state.show_sls user_management.users.manage

local:
    ----------
    /etc/skel:
        ----------
        __env__:
            base
        __sls__:
            user_management.users.manage
        file:
            |_
              ----------
              name:
                  /etc/skel
            |_
              ----------
              user:
                  root
            |_
              ----------
              group:
                  root
            |_
              ----------
              dir_mode:
                  755
            - directory
            |_
              ----------
              order:
                  10000
    /etc/skel/.bash_logout:
        ----------
        __env__:
            base
        __sls__:
            user_management.users.manage
        file:
            |_
              ----------
              name:
                  /etc/skel/.bash_logout
            |_
              ----------
              user:
                  root
            |_
              ----------
              group:
                  root
            |_
              ----------
              mode:
                  644
            |_
              ----------
              source:
                  salt://user_management/templates/etc/skel/bash_logout.sls
            - managed
            |_
              ----------
              order:
                  10001
    /etc/skel/.bash_profile:
        ----------
        __env__:
            base
        __sls__:
            user_management.users.manage
        file:
            |_
              ----------
              name:
                  /etc/skel/.bash_profile
            |_
              ----------
              user:
                  root
            |_
              ----------
              group:
                  root
            |_
              ----------
              mode:
                  644
            |_
              ----------
              source:
                  salt://user_management/templates/etc/skel/bash_profile.sls
            - managed
            |_
              ----------
              order:
                  10002
    /etc/skel/.bashrc:
        ----------
        __env__:
            base
        __sls__:
            user_management.users.manage
        file:
            |_
              ----------
              name:
                  /etc/skel/.bashrc
            |_
              ----------
              user:
                  root
            |_
              ----------
              group:
                  root
            |_
              ----------
              mode:
                  644
            |_
              ----------
              source:
                  salt://user_management/templates/etc/skel/bashrc.sls
            - managed
            |_
              ----------
              order:
                  10003
    group_csunderarajulu:
        ----------
        __env__:
            base
        __sls__:
            user_management.users.manage
        group:
            |_
              ----------
              name:
                  csunderarajulu
            |_
              ----------
              gid:
                  10001
            |_
              ----------
              system:
                  False
            - present
            |_
              ----------
              order:
                  10005
    group_mdresden:
        ----------
        __env__:
            base
        __sls__:
            user_management.users.manage
        group:
            |_
              ----------
              name:
                  mdresden
            |_
              ----------
              gid:
                  10000
            |_
              ----------
              system:
                  False
            - present
            |_
              ----------
              order:
                  10004
    user_csunderarajulu:
        ----------
        __env__:
            base
        __sls__:
            user_management.users.manage
        user:
            |_
              ----------
              name:
                  csunderarajulu
            |_
              ----------
              uid:
                  10001
            |_
              ----------
              gid:
                  10001
            |_
              ----------
              gid_from_name:
                  True
            |_
              ----------
              optional_groups:
                  - users
            |_
              ----------
              home:
                  /home/csunderarajulu
            |_
              ----------
              createhome:
                  True
            |_
              ----------
              password:
                  $6$wBMXk1u6Jxapb5GR$o4YckBYhVjZZ28vyOkcPwBLMH2tcgWAPqdqzLLOGGY5DCM1aaz/rNfnjpMdcmE4GFt/5dzwu8z3YXViptLTMT/
            |_
              ----------
              enforce_password:
                  True
            |_
              ----------
              empty_password:
                  False
            |_
              ----------
              shell:
                  /bin/bash
            |_
              ----------
              unique:
                  True
            |_
              ----------
              system:
                  False
            |_
              ----------
              fullname:
                  Chandrasekaran Sunderarajulu
            |_
              ----------
              require:
                  |_
                    ----------
                    group:
                        group_csunderarajulu
            - present
            |_
              ----------
              order:
                  10007
    user_mdresden:
        ----------
        __env__:
            base
        __sls__:
            user_management.users.manage
        user:
            |_
              ----------
              name:
                  mdresden
            |_
              ----------
              uid:
                  10000
            |_
              ----------
              gid:
                  10000
            |_
              ----------
              gid_from_name:
                  True
            |_
              ----------
              groups:
                  - wheel
            |_
              ----------
              optional_groups:
                  - users
            |_
              ----------
              home:
                  /home/mdresden
            |_
              ----------
              createhome:
                  True
            |_
              ----------
              password:
                  $6$wrBLmNvzyQcHsunt$N6qAv4QR/9A4oPb07zeBbdMQTG7dhxMt.5nXUYY3STwqyRlYvGi5G/GmItOu2M.wLzAOz0ClhEsQIUXMGwIwp1
            |_
              ----------
              enforce_password:
                  True
            |_
              ----------
              empty_password:
                  False
            |_
              ----------
              shell:
                  /bin/bash
            |_
              ----------
              unique:
                  True
            |_
              ----------
              system:
                  False
            |_
              ----------
              fullname:
                  Matthew Dresden
            |_
              ----------
              require:
                  |_
                    ----------
                    group:
                        group_mdresden
            - present
            |_
              ----------
              order:
                  10006

It produces the expected require group name. group_mdresden for example which is the name of the group that the state produces


Solution

  • Thanks Christophe Drevet-Drogue,

    The gid and uid in my state file was wrapped in double quotes. This caused it to be interpreted as a string rather than an integer which is what it was expecting. That issue caused all the other issued.

    So the answer to the original question is, the example I posted sufficiently accomplishes what I asked in the question.