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

have salt states be in another location than current directory #92

Open
ecks opened this issue Feb 6, 2017 · 15 comments
Open

have salt states be in another location than current directory #92

ecks opened this issue Feb 6, 2017 · 15 comments
Milestone

Comments

@ecks
Copy link

ecks commented Feb 6, 2017

I was not able to figure out a way to have the salt states be in a directory other than the current one where .kitchen.yaml is defined. For instance we have some_path/tests/kitchen_tests, where I would like to keep the yaml file. Then the actual salt state I want to use is in some_path/other_path/services/my_state_dir. It looks like the only way to get kitchen-salt to find the my_state_dir is if you put .kitchen.yaml inside the services dir.

It would be nice to have this functionality if it is not already there.

@ek9
Copy link
Contributor

ek9 commented Feb 7, 2017

I think this is similar to #83 . Can you please share your .kitchen.yml?

@ecks
Copy link
Author

ecks commented Feb 7, 2017

yea, essentially what I did was create a symbolic link to services dir in the current kitchen dir

---
driver:
  name: vagrant

platforms:
  - name: centos-7.3

provisioner:
  name: salt_solo
  salt_file_root: "/home/ecks/my_app/tests/kitchen_test/services"
  is_file_root: false
  require_chef: false
  state_top:
    base:
      '*':
        - users
        - my_state

suites:
  - name: server



verifier:
  name: shell
  command: testinfra ../infra_test/integration/$KITCHEN_SUITE

I quickly realized that salt_file_root refers to the root on the minion in vagrant, not on the host application. So I was trying different provisioner options but none of them worked. So now I have the following config inside services dir:

driver:
  name: vagrant

platforms:
  - name: centos-7.3

provisioner:
  name: salt_solo
  require_chef: false
  is_file_root: true
  state_top:
    base:
      '*':
        - users
        - my_app

suites:
  - name: server

verifier:
  name: shell
  command: testinfra infra_test/integration/$KITCHEN_SUITE

This works but is unfortunately undesired because we want to keep the testing code separate from the production code, ie the salt states.

@ek9
Copy link
Contributor

ek9 commented Feb 7, 2017

Thank you for the configuration. Could you give the directory tree information for your project (run tree path_to_formula) so I can understand the file-structure better?

Also, just a quick thought, would setting custom file_roots in minion's config would help? There's a PR for this that hasn't been merged yet.

@ecks
Copy link
Author

ecks commented Feb 7, 2017

❯❯❯ tree kitchen_test                                                  
kitchen_test
├── Gemfile
├── services -> ../../app/com/site/pivot/salt/salt/saltmaster/default/services
└── test
    ├── fixtures
    │   └── my_app.sls
    └── integration
        └── server
            └── testinfra
                └── test_my_app_server.py

Ideally I would not want to have that symbolic link there. This current setup does not work. I need to go right into the services dir and have that as my current working directory.

I believe if that PR is merged I can set file_roots to be /tmp/kitchen/srv/salt/services and it would work with that setup. What I would really would like to do is remove that symbolic link and just tell kitchen to copy all files from ../../app/com/site/pivot/salt/salt/saltmaster/default/services to the minion rather than start from the current dir. That way I wouldn't have to touch the minion config. Please lmk how difficult that would be to implement or whether there is another better solution.

@daks
Copy link
Contributor

daks commented Feb 7, 2017

In fact, I think we have a similar need. Mine is to have a file structure like this for my formula.

.
├── pillar.example
├── README.rst
├── test
│   ├── integration
│   │   └── default
│   │       ├── controls
│   │       │   ├── groups.rb
│   │       │   └── users.rb
│   │       └── inspec.yml
│   └── salt
│       └── default
│           ├── pillar
│           │   ├──  top.sls
│           │   └── usersandgroups.sls
│           └── states
│               ├── top.sls
│               └── users.sls
└── usersandgroups
    ├── files
    ├── init.sls
    └── map.jinja

It let testing code separated from production code.

@ek9
Copy link
Contributor

ek9 commented Feb 7, 2017

Thanks for extensive explanations. I understand the workflow, however I personally think this isn't a way to keep testing code separate from production code. I would view a git repository as part of development, thus the integration as such is done on the repository wise.

If you would use a proper distribution method (e.g. SPM), you could have .gitattributes file and specify the tests (and other non-production) directories to be excluded in the SPM builds. That way, you can package your production code appropriately. I would say cloning a development build on production is the real problem here :)

Still, I think a PR for this would be welcome and a nice addition so we can cover more use-cases.

@ek9
Copy link
Contributor

ek9 commented Feb 7, 2017

Linking #76 and #83 as all of these issues basically request same feature and I believe this one contains the most detailed information to issue a PR against.

@daks
Copy link
Contributor

daks commented Feb 8, 2017

For me, it's not a distribution problem, it's just a clarity one: to keep "real"/production/runtime code separated from testing one.
And maybe also a question of coherence, because in most (if not all) testing frameworks, you can keep your test code separated from the "real" code.

@ek9
Copy link
Contributor

ek9 commented Feb 8, 2017

@daks looking by your example, I see you would just like to have a separate tests folder, so your use case is rather standard practice that should definitely be supported by this formula. For the time being until we get a PR, you can accomplish this by defining states / pillars in the .kitchen.yml file directly.

@daks
Copy link
Contributor

daks commented Feb 8, 2017

@ek9 I agree with that, I want to have tests in the same repository as code, but I want to separate them in different directories.

@gtmanfred
Copy link
Contributor

Looks like there is an undocumented option, local_salt_root If you set this as a different directory besides the root directory, that should just sync those files to the sandbox.

Can you test that and let me know if solves this issue?

Thanks,
Daniel

@gtmanfred gtmanfred modified the milestones: Blocked, Approved Aug 30, 2017
@daks
Copy link
Contributor

daks commented Oct 31, 2017

I tried to use this undocumented option, removing all previous use of pillars/state_top/pillars-from-files. My kitchen.yml looks like

driver:
  name: vagrant
  provision: false

provisioner:
  name: salt_solo
  formula: haproxy
  salt_install: bootstrap
  require_chef: false
  local_salt_root: test/salt/default

and directory is

tree test/salt/default/
test/salt/default/
├── pillar
│   ├── hosts.sls
│   └── top.sls
└── salt
    ├── hosts.sls
    └── top.sls

When I login to the Kitchen VM, pillar seems ok but not states

# tree /tmp/kitchen/srv/
/tmp/kitchen/srv/
|-- pillar
|   |-- hosts.sls
|   `-- top.sls
`-- salt
    |-- haproxy
    |   |-- hosts.sls
    |   `-- top.sls
    `-- top.sls

# cat pillar/top.sls
base:
  '*':
    - hosts

# cat salt/top.sls
--- {}

I'm not sure if I need to use this option with other ones, I'll try some.

[update] seems my original salt/ directory became salt/haproxy one.
This option works for pillar files but not for states.

Moreover I'm not the sure it's the solution to my problem because I don't find my original formula directory.

@anuriq
Copy link

anuriq commented Dec 15, 2017

Hi @gtmanfred
I think, there is a documentation problem here. After reading this https://github.com/saltstack/kitchen-salt/blob/master/docs/provisioner_options.md#state_top_from_file it feels like i can provide a path to a file and it will be used as top.sls, but in reality (after looking into code) this is just a trigger true/false.

@gtmanfred
Copy link
Contributor

@anuriq that does not appear to be related to this issue, can you open a new issue?

Thanks,
Daniel

@kquinsland
Copy link

My god, that took a while to figure out.


Like many of you, I have a repo that looks like this:

(lightly edited)

❯ tree .
.
├── docs
│   └── kitchen
│       ├── readme.md
│       └── set-up-kitchen.md
├── Gemfile
├── Gemfile.lock
├── _kitchen
│   └── minion.erb
├── kitchen.yml
├── pillars
│   ├── base
│   │   ├── common
│   │   │   ├── data.sls
│   │   │   └── packages.sls
# <...>
│   └── readme.md
├── readme.md
├── states
│   ├── core
│   │   ├── init.sls
│   │   ├── ubuntu
│   │   │   └── remove_snapd.sls
│   │   └── users.sls
│   └── top.sls
└── tests

Basically ONE repo with a states and pillars sub dir.

After reading through this thread and the docs and the code, I didn't find any combination of flags in the kitchen.yml that would work.
One way or another, something was always copied to the wrong location.

I finally found a way to make it work, but it's not pretty.

Here is a sanitized version of my kitchen.yml:

driver:
    # See: https://github.com/test-kitchen/kitchen-docker
    name: docker
    # <...>

platforms:
    # If no version explicitly set, will default to latest
    - name: ubuntu
      driver_config:
          run_command: /lib/systemd/systemd

transport:
    name: rsync

# What kitchen will use to converge the state/test instance
provisioner:
    name: salt_solo
    # Note: periodically, this will need to be updated/refreshed
    salt_bootstrap_url: https://github.com/saltstack/salt-bootstrap/releases/download/v2024.11.27/bootstrap-salt.sh

    # Wait for ssh before provisioning
    install_after_init_environment: true

    is_file_root: true

# Actual salt states to test
suites:
    # Test core/init.sls
    - name: core
      provisioner:
          salt_env: base
          salt_pillar_root: /srv/salt/pillars

          # There is something fucky and non-obvious about how the files are copied around.
          # The docs are leave both thoroughness and accuracy to be desired!!!
          # After a lot of trial/error, I think this is the cheapest hack that uses kitchen purely as a "copy everything in, just call salt"
          #     tool.
          salt_minion_config_template: _kitchen/minion.erb
          # -X disables daemon after install which is exactly what we want w/ an ephemeral container
          salt_bootstrap_options: -X -p git -p nano stable

verifier:
    #<...>

Really, the key is that I am NOT trying to configure any of the "helpful" path modification things that mess w/ where stuff gets copied to.
I am using the most basic "just rsync it all over, please" config.
I want to use the top.sls file that is in my repo already as well.

The critical bit that makes this all work is my custom minion.erb file.

# Cut down copy of
# https://github.com/saltstack/kitchen-salt/blob/03a438aadf8c73b8e49820d21f44a468e0632901/lib/kitchen/provisioner/minion.erb
# @markup text
local: true
state_top: top.sls
root_dir: <%= config[:root_path] %>

# Hello from my minion.erb template!
file_roots:
 <%= config[:salt_env] %>:
   - <%= os_join(config[:root_path], config[:salt_file_root], 'states') %>

pillar_roots:
 <%= config[:pillar_env] || config[:salt_env] %>:
   - <%= os_join(config[:root_path], config[:salt_pillar_root], 'pillars') %>

Essentially this is the same as the default one (minus windows stuff; don't use it) but I am ADDING the /states and /pillars to the end of the paths.

I hope this helps someone else. I spent a lot of time on this and I hope to save someone else some time.

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

No branches or pull requests

6 participants