├── .gitignore ├── DOCKER_OLD ├── Dockerfile ├── LICENSE ├── NOTICE ├── README.rst ├── conf ├── base.txt ├── basic.conf ├── default_run.py ├── network.yml └── network_requirements.txt ├── exclude.txt ├── mk_repo.py ├── requirements.txt └── scripts └── cent6_setup.sh /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[codx] 4 | 5 | # C extensions 6 | *.so 7 | 8 | # Ignore generated C files (Cython) 9 | *.c 10 | 11 | # iPython notebooks and checkpoints 12 | *.ipynb 13 | .ipynb_checkpoints 14 | 15 | # patch files 16 | *.orig 17 | 18 | # Don't commit Ubu SPA 19 | raas/static/* 20 | 21 | # Don't commit a deploy-key 22 | deploy-key 23 | 24 | # Distribution / packaging 25 | .Python 26 | env/ 27 | bin/ 28 | build/ 29 | develop-eggs/ 30 | dist/ 31 | eggs/ 32 | lib/ 33 | lib64/ 34 | parts/ 35 | sdist/ 36 | var/ 37 | *.egg-info/ 38 | .installed.cfg 39 | *.egg 40 | MANIFEST 41 | 42 | # Installer logs 43 | pip-log.txt 44 | pip-delete-this-directory.txt 45 | 46 | # Unit test / coverage reports 47 | htmlcov/ 48 | .tox/ 49 | .coverage 50 | .cache 51 | .pytest_cache 52 | nosetests.xml 53 | coverage.xml 54 | 55 | # Pytest 56 | pytest.ini 57 | 58 | # Translations 59 | *.mo 60 | 61 | # macOS 62 | .DS_Store 63 | 64 | # Mr Developer 65 | .mr.developer.cfg 66 | .project 67 | .pydevproject 68 | 69 | # Rope 70 | .ropeproject 71 | 72 | # Django stuff: 73 | *.log 74 | *.pot 75 | 76 | # Sphinx documentation 77 | doc/_build/ 78 | doc/user/ubu/_build/ 79 | 80 | # Local VIM RC 81 | .lvimrc 82 | 83 | # Swap files 84 | .*.swp 85 | 86 | # nvim 87 | *.un~ 88 | *~ 89 | 90 | # setup compile left-overs 91 | *.py_orig 92 | 93 | # Tags 94 | TAGS 95 | tags 96 | 97 | # kdevelop 98 | *.kdev4 99 | 100 | # pycharm 101 | .idea* 102 | 103 | # VSCode 104 | .vscode* 105 | 106 | # pyenv 107 | .python-version 108 | 109 | .ci/.rootdir 110 | 111 | # Coverage data files 112 | .coverage.* 113 | 114 | # vscode 115 | .vscode 116 | .pytest_cache 117 | 118 | -------------------------------------------------------------------------------- /DOCKER_OLD: -------------------------------------------------------------------------------- 1 | Docker Build 2 | ============ 3 | 4 | THIS IS AN OLD BUILD INSTRUCTION, IT IS HERE UNTIL I CAN GET NEWER PYTHONS 5 | TO RUN ON PYENV WITH OLD CENTOS. 6 | 7 | DO NOT USE THIS TUTORIAL 8 | 9 | It may be desireable to build the binary in a docker container. For instance 10 | building in a centos 6 container should product a more portable binary. 11 | 12 | `salt-bin` comes with a script for building in centos 6 with a newer python. 13 | To build make a new docker container: 14 | 15 | docker run -it centos:6 bash 16 | 17 | Then copy the files into the container: 18 | 19 | docker cp . :/opt 20 | 21 | Then run the build: 22 | 23 | cd /opt 24 | 25 | bash scripts/cent6_setup.sh 26 | 27 | The results will be in the dist directory where they can be coppied back out with 28 | the docker cp command: 29 | 30 | docker cp :/opt/dist . 31 | 32 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM centos:6 2 | 3 | WORKDIR /opt 4 | #VOLUME . /opt 5 | RUN bash /opt/scripts/cent6_setup.sh 6 | RUN cp /opt/dist/* /tmp/results 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Redistribution and use in source and binary forms, with or without 2 | modification, are permitted provided that the following conditions are 3 | met: 4 | 5 | 1. Redistributions of source code must retain the above copyright 6 | notice, this list of conditions and the following disclaimer. 7 | 8 | 2. Redistributions in binary form must reproduce the above 9 | copyright notice, this list of conditions and the following 10 | disclaimer in the documentation and/or other materials provided 11 | with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 14 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 15 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 16 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 17 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 18 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 19 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Copyright 2022 VMware, Inc. 2 | 3 | This product is licensed to you under the BSD 2 clause (the "License"). You may not use this product except in compliance with the License. 4 | 5 | This product may include a number of subcomponents with separate copyright notices and license terms. Your use of these subcomponents is subject to the terms and conditions of the subcomponent's license, as noted in the LICENSE file. -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | ======== 2 | Salt Bin 3 | ======== 4 | 5 | The Salt Bin project is here to allow for single binary builds of Salt 6 | to be easy to make and distribute. Distributing Python applications is 7 | notoriously difficult, and while there are MANY tools that seek to solve 8 | this problem, they can't do it in a universal way. 9 | 10 | How 11 | ==== 12 | 13 | Salt-bin is a collection of requirements and configurations to build 14 | distributions of Salt for specific platforms and use cases. 15 | 16 | We use pop's build system, as it is built to handle a superset of the 17 | challenges found in building Salt. So to use salt-bin you call out to 18 | the `pop-build` executable. 19 | 20 | The pop build system can also make use of `pyenv` to make the builds 21 | target specific versions of python. This allows us to build Salt with 22 | the same version of Python across MANY platforms, which allows for 23 | more rapid development and platform consistency. 24 | 25 | Usage 26 | ===== 27 | 28 | Install pop-build: 29 | 30 | * pip install pop-build 31 | 32 | It is a good idea to install pyenv as well, see the pyenv install page: 33 | 34 | https://github.com/pyenv/pyenv#installation 35 | 36 | Now clone the repo: 37 | 38 | * git clone https://github.com/saltstack/salt-bin.git 39 | * cd salt-bin 40 | 41 | Inside the repo you will find a collection of requirements files and configs. 42 | The configuration files are for pop-build and can be found in the conf directory. 43 | 44 | Inside this directory you can make a "basic" build of salt by just calling 45 | 46 | * pop-build -c conf/basic.conf 47 | 48 | If you have pyenv installed, you can build your binary against a specific version 49 | of Python. Just add the `pyenv` option: 50 | 51 | * pop-build -c conf/basic.conf --pyenv 3.7.6 52 | 53 | To see the available python versions you can build against run: 54 | 55 | * pyenv install --list | grep " 3\.[6789]" 56 | 57 | Extending Salt-Bin 58 | ================== 59 | 60 | Salt-bin is not a python project, it is a collection of configurations used to 61 | make different builds of `Salt` depending on platform and intended use. Salt 62 | does not require that all imaginable deps are included, so salt-bin comes with 63 | configs to install for specific needs and targets. 64 | 65 | Salt-bin is extended by adding more build configs for specific platforms. Since 66 | salt-bin is just a collection of `pop-build` configs, you just need to add more 67 | `pop-build` configs. 68 | 69 | Add a config file in the conf directory and a requirements.txt file, along with 70 | any other needed files. Take a look at conf/base.conf as an example. 71 | 72 | Pop-Build Config 73 | ================ 74 | 75 | The `pop-build` config takes a number of options: 76 | 77 | name 78 | ---- 79 | 80 | The name value defines the name of the binary to build, in the case of `salt-bin` 81 | this should always be `salt` 82 | 83 | run 84 | ---- 85 | 86 | The run option allows for a specific `run.py` file to be used as the entry point. This 87 | makes it easy to have a custom entry point that only exposed specific components of 88 | Salt in the binary. 89 | 90 | requirements 91 | ------------ 92 | 93 | The requirements value points to the requirements file to be used to install deps, 94 | `pop-build` relied on pip to gather the deps during the build and reads a standard 95 | python `requirements.txt` file. 96 | 97 | exclude 98 | ------- 99 | 100 | Sometimes it is useful to exclude specific deps, this can be done by adding those 101 | deps into an `exclude.txt` file. This allows you to uninstall python libs from the 102 | binary. 103 | 104 | build 105 | ----- 106 | 107 | Sometimes a separate .so or .dll is needed to support a specific python library and 108 | they are not always installed with the python code installed via pip. To add a 109 | support dynamic library it can be included in the build tool of `pop-build`. 110 | 111 | To use this define the `build` option in the config. This option then takes 112 | an arbitrary number of projects to build into the binary. The build section 113 | can build from the sources: 114 | 115 | * build: 116 | * libsodium: 117 | * make: 118 | * - wget https://download.libsodium.org/libsodium/releases/LATEST.tar.gz 119 | * - tar xvf LATEST.tar.gz 120 | * - cd libsodium-stable && ./configure && make 121 | * src: libsodium-stable/src/libsodium/.libs/libsodium.so 122 | * dest: lib/ 123 | 124 | This example will download the sources to libsodium, untar them, and compile them. 125 | Then from the compiled code the sources can be set, this is either a single file 126 | or a list of files. Finally the `dest` defines the directory within the binary's 127 | environment where to save the needed artifacts. 128 | -------------------------------------------------------------------------------- /conf/base.txt: -------------------------------------------------------------------------------- 1 | salt 2 | Jinja2 3 | distro 4 | # This should be changed to msgpack-python for Packages 5 | # msgpack-python>0.3,!=0.5.5 6 | msgpack>=0.5,!=0.5.5 7 | PyYAML<5.1 8 | MarkupSafe 9 | requests>=1.0.0 10 | tornado>=4.2.1,<6.0; python_version < '3' 11 | tornado>=4.2.1,<5.0; python_version >= '3.4' 12 | 13 | # Required by Tornado to handle threads stuff. 14 | futures>=2.0; python_version < '3.0' 15 | pycryptodomex 16 | 17 | # TODO: Building with a custom openssl 1.1.1 on centos 6 is failing to compile M2Crypto, this should be fixed in the future as M2Crypto is prefered 18 | #M2Crypto>=0.35.2 19 | -------------------------------------------------------------------------------- /conf/basic.conf: -------------------------------------------------------------------------------- 1 | pop_build: 2 | name: salt 3 | requirements: conf/base.txt 4 | run: conf/default_run.py 5 | system_copy_in: distutils 6 | -------------------------------------------------------------------------------- /conf/default_run.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | #!/usr/bin/env python3 3 | 4 | # Import python libs 5 | import sys 6 | import os 7 | import multiprocessing 8 | 9 | # Import salt libs 10 | import salt.scripts 11 | import salt.utils.platform 12 | 13 | # Import third party libs 14 | from pip._internal.cli.main import main 15 | 16 | 17 | AVAIL = ( 18 | 'minion', 19 | 'master', 20 | 'call', 21 | 'api', 22 | 'cloud', 23 | 'cp', 24 | 'extend', 25 | 'key', 26 | 'proxy', 27 | 'pip', 28 | 'run', 29 | 'shell', 30 | 'ssh', 31 | 'support', 32 | 'syndic', 33 | ) 34 | 35 | 36 | def redirect(): 37 | ''' 38 | Change the args and redirect to another salt script 39 | ''' 40 | if len(sys.argv) < 2: 41 | msg = 'Must pass in a salt command, available commands are:' 42 | for cmd in AVAIL: 43 | msg += '\n{0}'.format(cmd) 44 | print(msg) 45 | sys.exit(1) 46 | cmd = sys.argv[1] 47 | if cmd == "shell": 48 | py_shell() 49 | return 50 | elif cmd == "pip": 51 | pip() 52 | return 53 | elif cmd not in AVAIL: 54 | # Fall back to the salt command 55 | sys.argv[0] = 'salt' 56 | s_fun = salt.scripts.salt_main 57 | else: 58 | sys.argv[0] = 'salt-{0}'.format(cmd) 59 | sys.argv.pop(1) 60 | s_fun = getattr(salt.scripts, 'salt_{0}'.format(cmd)) 61 | s_fun() 62 | 63 | 64 | def py_shell(): 65 | import readline # optional, will allow Up/Down/History in the console 66 | import code 67 | variables = globals().copy() 68 | variables.update(locals()) 69 | shell = code.InteractiveConsole(variables) 70 | shell.interact() 71 | 72 | 73 | def pip(): 74 | cmd = sys.argv[2] 75 | args = [cmd, '--target', sys._MEIPASS,] 76 | args.extend(sys.argv[3:]) 77 | parser = ['pip'] + args 78 | sys.argv = parser 79 | main(args) 80 | 81 | 82 | if __name__ == '__main__': 83 | if sys.platform.startswith('win'): 84 | multiprocessing.freeze_support() 85 | redirect() 86 | -------------------------------------------------------------------------------- /conf/network.yml: -------------------------------------------------------------------------------- 1 | requirements: conf/network_requirements.txt 2 | -------------------------------------------------------------------------------- /conf/network_requirements.txt: -------------------------------------------------------------------------------- 1 | -r conf/base.txt 2 | napalm 3 | -------------------------------------------------------------------------------- /exclude.txt: -------------------------------------------------------------------------------- 1 | # Make sure that pycryptodome or M2Crypto gets used 2 | pycrypto 3 | # This breaks Windows builds and is not needed on python 3.6/3.7 4 | enum34 5 | -------------------------------------------------------------------------------- /mk_repo.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Create the repo files used by heist to read what files are available 3 | ''' 4 | # Import python libs 5 | import os 6 | import json 7 | import pprint 8 | import hashlib 9 | from distutils.version import StrictVersion 10 | 11 | # Import third party libs 12 | import msgpack 13 | 14 | LATEST = 'salt' 15 | 16 | 17 | def scan(): 18 | data = {} 19 | for root, dirs, files in os.walk('dist'): 20 | if root == 'dist': 21 | continue 22 | base = os.path.basename(root) 23 | data[base] = {} 24 | for fn in files: 25 | if fn == LATEST: 26 | continue 27 | data[base][fn] = { 28 | 'name': fn, 29 | 'version': fn[fn.index('-')+1:] 30 | } 31 | full = os.path.join(root, fn) 32 | with open(full, 'rb') as rfh: 33 | raw = rfh.read() 34 | data[base][fn]['blake'] = hashlib.blake2b(raw).hexdigest() 35 | data[base][fn]['sha512'] = hashlib.sha512(raw).hexdigest() 36 | data[base][fn]['sha3_512'] = hashlib.sha3_512(raw).hexdigest() 37 | 38 | for base, rels in data.items(): 39 | names = [] 40 | for fn, rel in rels.items(): 41 | names.append(rel['version']) 42 | names = sorted(names, key=StrictVersion) 43 | latest = os.path.join(f'salt-{names[-1]}') 44 | latest_lk = os.path.join('dist', base, 'salt') 45 | if os.path.exists(latest_lk): 46 | os.remove(latest_lk) 47 | os.symlink(latest, latest_lk) 48 | with open('dist/repo.mp', 'wb+') as wfh: 49 | wfh.write(msgpack.dumps(data)) 50 | with open('dist/repo.json', 'w+') as wfh: 51 | wfh.write(json.dumps(data)) 52 | 53 | 54 | scan() 55 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | pop-build 2 | -------------------------------------------------------------------------------- /scripts/cent6_setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | PYVER='3.7.4' 3 | PYPRE='3.7' 4 | 5 | yum install -y xz libffi-devel bzip2-devel xz-devel ncurses-devel gdbm-devel sqlite-devel readline-devel zlib-devel libuuid-devel 6 | yum groupinstall -y 'Development Tools' 7 | 8 | curl -LO https://www.openssl.org/source/openssl-1.1.1d.tar.gz 9 | tar -xvf openssl-1.1.1d.tar.gz 10 | 11 | cd openssl-1.1.1d 12 | ./config shared --prefix=/usr/local/openssl11 --openssldir=/usr/local/openssl11 && make && make install 13 | cd .. 14 | 15 | curl -LO https://www.python.org/ftp/python/3.7.4/Python-3.7.4.tar.xz 16 | tar xvf Python-3.7.4.tar.xz 17 | cd Python-3.7.4 18 | # Edit Modules/Setup.dist 19 | LDFLAGS="-Wl,-rpath=/usr/local/openssl11/lib" ./configure --prefix=/usr/local/python37 --with-openssl=/usr/local/openssl11 --with-system-ffi --enable-shared && make && make install 20 | cd .. 21 | 22 | ln -s /usr/local/python37/bin/*3.7* /usr/local/bin 23 | ln -s /usr/local/python37/bin/pip3.7 /usr/local/bin/pip3 24 | export LD_LIBRARY_PATH=/usr/local/python37/lib/:/usr/local/openssl11/lib/ 25 | LD_LIBRARY_PATH=/usr/local/python37/lib/:/usr/local/openssl11/lib/ pip3 install staticx 26 | ln -s /usr/local/python37/bin/staticx /usr/local/bin/staticx 27 | cd /opt 28 | LD_LIBRARY_PATH=/usr/local/python37/lib/:/usr/local/openssl11/lib/ python3.7 build.py -S 29 | --------------------------------------------------------------------------------