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

salt.states.pkg add check if package installed in system, without installation/removal of package #39744

Closed
Anton-Latukha opened this issue Mar 1, 2017 · 9 comments
Labels
Duplicate Duplicate of another issue or PR - will be closed
Milestone

Comments

@Anton-Latukha
Copy link

Anton-Latukha commented Mar 1, 2017

Description of Issue/Question

Add to salt.states.pkg function to check if package installed or not present, but without further installation or removal.

There are one-liners for many applications.
One-liners:

  • are provided and maintained by official upstream developers team
  • detect your platform and install applications by official upstream way on that platform, so you don't need to hustle with templates
  • that is why official one-liners used as convenient, unified way to install application proper way not depending on underline distribution/platform in complex infrastructures, probably many enterprise guys use this shortcut
  • is the fastest automatic way to install on any distribution/platform
  • if script can't do install - it throws error - cmd.run catches it
sudo salt '*' grains.ls

Does not have grains that can say me if package installed.

Using a module, I can do:

salt 'ID' pkg.version _package_

That returns version, if package installed, None, if package is not installed.

But I think this functionality is obviously must be present in salt.states.pkg. We install packages there, we remove packages there, we update packages there, and probably we need to check if it installed?

So we don't need to hack-around, putting module commands in cmd.run states and referencing to them from one-liner cmd.run, in sls files.

As I understand, states and modules must share code, so enabling just check in salt.states.pkg is easy.

Anyway it is already used by salt.states.pkg in chains of action, but we can not say not to install or remove package, just check in system.


Example:

I want to use official installation script: https://get.docker.com/

Or for our fun, lets assume I want to use Salt https://bootstrap.saltstack.com in containers directly. For testing/learning purposes run states in test containers - is great approach.

Because, depending on platform - Docker/Salt installs differently. Example:

  • On Ubuntu - official way is to use not default Ubuntu package - use upstream Docker PPA, also install depends on the version of Ubuntu
  • On Arch you can use current package
  • On Alpine is other way
  • On other systems - other way of install.
    Docker team / Salt team manages this for us in this one-liners.

I want to check, does package installed, if not - run one-liner.

I don't need to think about what platform I use, after automatic onle-liner was done, if I want to update Docker version - I just use salt.states.pkg.latest against docker package.

But without function to check if package installed I need to adapt to platform, to check if Docker installed. Without that cmd.run does one-liner every time I run sls.

I saw and tested return parameter, because it sort-of states what I need, but is not clear in documentation what this parameter does.

docker:
  pkg.installed:
    - return:

It bluntly installs docker. I don't need that, I need only to check, does package installed.


Setup

docker_not_installed:
  pkg._check_

curl -sSL https://get.docker.com/ | sh
  cmd:
    - run
    - ifonly: docker_not_installed

OR

docker_installed:
  pkg._check_

curl -sSL https://get.docker.com/ | sh
  cmd:
    - run
    - unless: docker_installed

Steps to Reproduce Issue

Use any one-liner, like https://get.docker.com/, where official one-liner manages proper install for you.

But then you need to add check that application is not installed in system, so one-liner runs only when application not installed.

The most straight way on most systems is to check if the package installed.

Otherwise we must rely that one-liner just exits with zero code if application already installed, not throws error, or thinks that we want to do reinstall procedure every time.

Versions Report

Is probably not relevant, in devel docks I found nothing.

Salt Version:
Salt: 2016.11.2

Dependency Versions:
cffi: Not Installed
cherrypy: unknown
dateutil: 2.6.0
gitdb: Not Installed
gitpython: Not Installed
ioflo: Not Installed
Jinja2: 2.9.5
libgit2: Not Installed
libnacl: Not Installed
M2Crypto: 0.24.0
Mako: Not Installed
msgpack-pure: Not Installed
msgpack-python: 0.4.8
mysql-python: Not Installed
pycparser: Not Installed
pycrypto: 2.6.1
pygit2: Not Installed
Python: 2.7.13 (default, Dec 21 2016, 07:16:46)
python-gnupg: Not Installed
PyYAML: 3.12
PyZMQ: 16.0.2
RAET: Not Installed
smmap: Not Installed
timelib: Not Installed
Tornado: 4.4.2
ZMQ: 4.2.0

System Versions:
dist:
machine: x86_64
release: 4.9.11-1-ARCH
system: Linux
version: Not Installed


P.S.
I don't know, maybe hack-around and feeding module commands to states is a right way, or it is not really Salt way, I rely on your experience.

@gtmanfred
Copy link
Contributor

The unless and onlyif commands are only for specifying shell commands, so you would need to do rpm -q docker, or use salt to manage the docker repository and installing the package, and stop using the script.

#20307

This appears to be a duplicate of the above

Thanks,
Daniel

@gtmanfred gtmanfred added the Duplicate Duplicate of another issue or PR - will be closed label Mar 1, 2017
@gtmanfred gtmanfred added this to the Blocked milestone Mar 1, 2017
@Anton-Latukha
Copy link
Author

Anton-Latukha commented Mar 2, 2017

  1. No it is not a duplicate.
    I talk about what's in unless and onlyif should run salt execution modules #20307 as a hack to solve my question.

  2. You pasted me a solution from stack-exchange. Why you assumed my distro.

I show you how to do cross-distribution way and you respond: use RPM -q.
Ok. What if I use Alpine Linux?

By official way of Salt, for now, I need to manually do a template and describe install on every possible distribution of some solution. Then I need to manually do a template to describe how to check does package installed, on every possible distribution.
Than I need to sit on upstream news of solution and synchronize my manually maintained templates with official installation processes on different distributions.

This is what you suggested me in favour of official one-liner install scripts that already do that by official way on any supported distribution.

One-liners are official, and highly officially maintained source to install solutions. Salt official documentation uses one-liner as main way of install https://docs.saltstack.com/en/latest/topics/installation/#quick-install.

Sorry, I see you missed my point. What you suggest is what I already implemented.

I show there is no way to check if package installed, in the state file. That is all.

Man, I envy you. You talk with so many best IT guys in such great Enterprise product, you can learn so much by digging-in.

P.S.
Probably I better use which <binary>

@gtmanfred
Copy link
Contributor

Right, the issue I linked to was to be able to use salt modules in the unless and only if array.

So, you could do pkg.is_installed <pkgname> in the unless, and it would check if the pkg was installed, independently of which package manager/distribution you are using. With what is talked about in that issue, you would not need to template your unless/onlyif arguments.

So the state would look like this

curl -sSL https://get.docker.com/ | sh
  cmd.run:
    - unless:
      - pkg.is_installed: docker

or something like that.

@gtmanfred
Copy link
Contributor

gtmanfred commented Mar 2, 2017

You should also be able to do exactly what you are trying to do using the following.

install docker:
  pkg.installed:
    - name: docker-engine
    - test: True

  cmd.script:
    - name: https://get.docker.com/
    - prereq:
      - pkg: docker-engine

Or possibly this to run if it is unable to install docker-engine

install docker:
  pkg.installed:
    - name: docker-engine

  cmd.script:
    - name: https://get.docker.com/
    - onfail_in:
      - pkg: docker-engine

The basics of those scripts is to just setup repositories, and install the packages.

@Anton-Latukha
Copy link
Author

Anton-Latukha commented Mar 2, 2017

This is great response.

You can read titles, beyond them are more information on that title.

1. - pkg.is_installed: <package> isn't working, isn't exist in documentation anywhere.

It did not exist in "salt.states.pkg" documentation. And I can't find it anywhere else. If there was documentation on it, I would use it and not write this report.

I do testing, echo must return STDOUT only if pkg.is_installed:

echo 'Package is installed!':
  cmd.run:
    - onlyif:
      - pkg.is_installed: zsh

Installed zsh package or not - results in:

          ID: echo 'Test, Package is installed!'
    Function: cmd.run
      Result: True
     Comment: onlyif execution failed: OrderedDict([('pkg.is_installed', 'zsh')])
     Started: 18:05:07.691929
    Duration: 19.49 ms
     Changes:   

So it is always throws error.

2. Using -test: True in state like that is undocumented.

It is not mentioned in "salt.states.pkg". It can be a feature there (what we trying to do).

In "Requisites and Other Global State Arguments":

When a prereq requisite is evaluated, the pre-required state reports if it expects to have any changes. It does this by running the pre-required single state as a test-run by enabling test=True.

So it get minorly mentioned in small paragraph.
"Requisites and Other Global State Arguments" seams like a real place to cover -test: True and to cross-link with "State Testing".

It is described in "State Testing", which is not referenced anywhere of the above, but as a added key, test=True, not using it like -test: True in state as a feature. And in scope of article on testing - it is not virtually get related to what we are using it for here. But it is a feature.

...
If it worked.

3. -test: True doesn't work as expected in pkg state, and actions get executed, this poisons prereq also. It is already in many open bug reports.

There are many bug-reports on execution of actions, while test key used.
And therefore it poisons prereq functionality (#30892). I see they mention pkg.installed here, it is what I hit. Looks like @Ch3LL there bisected and blamed commit.

Package get installed on test of pkg.installed.

install zsh:
  pkg.installed:
    - name: zsh
    - test: True

Results in nasty:

          ID: install zsh
    Function: pkg.installed
        Name: zsh
      Result: True
     Comment: The following packages were installed/updated: zsh
     Started: 16:45:53.260124
    Duration: 14802.46 ms
     Changes:   
              ----------
              zsh:
                  ----------
                  new:
                      5.2-5ubuntu1
                  old:

And package really get installed, while we in test mode.

Versions Report:

Master version info mentioned in first post.
Minion is:

Salt Version:
           Salt: 2016.11.2
 
Dependency Versions:
           cffi: Not Installed
       cherrypy: Not Installed
       dateutil: 2.4.2
          gitdb: Not Installed
      gitpython: Not Installed
          ioflo: Not Installed
         Jinja2: 2.8
        libgit2: Not Installed
        libnacl: Not Installed
       M2Crypto: Not Installed
           Mako: 1.0.4
   msgpack-pure: Not Installed
 msgpack-python: 0.4.8
   mysql-python: Not Installed
      pycparser: Not Installed
       pycrypto: 2.6.1
         pygit2: Not Installed
         Python: 2.7.12+ (default, Sep 17 2016, 12:08:02)
   python-gnupg: Not Installed
         PyYAML: 3.11
          PyZMQ: 15.2.0
           RAET: Not Installed
          smmap: Not Installed
        timelib: Not Installed
        Tornado: 4.4.2
            ZMQ: 4.2.0
 
System Versions:
           dist: Ubuntu 16.10 yakkety
        machine: x86_64
        release: 4.8.0-39-generic
         system: Linux
        version: Ubuntu 16.10 yakkety

P.S.
We have two undocumented features, one not working, other with a bug.

Say your judgement what we should do with this. I can do more salt-dev build and more work on it.

@gtmanfred
Copy link
Contributor

pkg.is_installed is a hypothetical and doesn't exist ... yet.

Also, it looks like I was mistaken and that test: True is not a state Runtime keyword that could be used in this way.

And again, this

echo 'Package is installed!':
  cmd.run:
    - onlyif:
      - pkg.is_installed: zsh

Is a proposed way to do the onlyif and unless in the feature request that I said this request is a duplicate of.

@Anton-Latukha
Copy link
Author

Ok. Now we looked deeper, and it is really covered by other reports.

I going to wait on that features resolved.

Thank you great to work with you.

@yashgude7
Copy link

@gtmanfred I'm new to salt. I want to write an SLS file to list all the available updates on a particular minion. I'm applying the state on minion itself on our salt dashboard portal. I wrote a small snippet that is pasted below. The result shows success but doesn't give output in a list format or something like that.

SLS file
list_updates:
module.run:
- name: pkg.list_pkgs

@oliver-dungey
Copy link

A bit late to the party but this whole thread confused me until I worked out a solution - use the Linux which command to search for a binary on the search path and combine this with onlyif. So an example:

Open Firewall ports for Samba:
  cmd.run:
    - name: firewall-cmd --permanent --add-port={139/tcp,445/tcp}
    - onlyif: 'which firewall-cmd'

Will only run the command if it finds firewall-cmd on the search path. Nice and simple.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Duplicate Duplicate of another issue or PR - will be closed
Projects
None yet
Development

No branches or pull requests

4 participants