https://github.com/rhcarvalho/envdiff
Smart environment diffs
https://github.com/rhcarvalho/envdiff
diff docker dockerfile env fedora redhat scl shell software-collections
Last synced: about 2 months ago
JSON representation
Smart environment diffs
- Host: GitHub
- URL: https://github.com/rhcarvalho/envdiff
- Owner: rhcarvalho
- Created: 2016-03-29T16:13:53.000Z (about 9 years ago)
- Default Branch: master
- Last Pushed: 2016-03-31T17:29:44.000Z (about 9 years ago)
- Last Synced: 2025-01-16T22:12:54.399Z (4 months ago)
- Topics: diff, docker, dockerfile, env, fedora, redhat, scl, shell, software-collections
- Language: Go
- Size: 15.6 KB
- Stars: 2
- Watchers: 3
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# envdiff
Generates smart environment diffs.
The `envdiff` tool compares two environments, and tries to be smart where it
can. For example, it can detect appends or prepends to lists like `PATH`.Given two environments `A` and `B`, `envdiff` computes `C` such that:
```
(export A; export C) == export B
```Examples [here](#using).
## Installing
You will need to have the `go` tool [installed](https://golang.org/doc/install),
then:```
go get -u github.com/rhcarvalho/envdiff
```Now `envdiff` should be in your PATH.
## Using
`envdiff` takes two arguments that should contain a list of newline or null-byte
separated environment variables.Examples:
1. Detecting new variables:
```console
$ envdiff TERM=xterm $'TERM=xterm\nFOO=bar'
FOO=bar
```2. Detecting removed variables:
```console
$ envdiff $'TERM=xterm\nFOO=bar' TERM=xterm
FOO=
```3. Detecting changing of a list:
```console
$ envdiff PATH=/bin:/sbin PATH=/usr/bin/:/usr/sbin:/bin:/sbin
PATH=/usr/bin/:/usr/sbin:$PATH
```## How to reverse-engineer a Software Collection for Docker images
By detecting environment changes introduced by enabling certain [Software
Collections](https://www.softwarecollections.org) (SCL) and writing a Dockerfile
ENV instruction that has the same effect, one can create Docker images that have
the given collections enabled by default.For example, if you install a Ruby collection in a CentOS image, you might as
well want to have the `ruby` binary in your PATH. A user of your image need not
to know about SCL or have to do any extra steps to be able to run a line like:```
docker run --rm scl-enabled-ruby-image ruby -e 'puts "Hello World!"'
```Great, how do I do that with `envdiff`? There's really only **one** required
step!1. Point `envdiff` at your target image:
```console
$ envdiff -o docker scl openshift/ruby-20-centos7
# -- generated by https://github.com/rhcarvalho/envdiff, do not edit manually --
# The ENV instruction below is equivalent to:
# scl enable nodejs010 ror40 ruby200 v8314
ENV MANPATH=/opt/rh/v8314/root/usr/share/man:/opt/rh/ruby200/root/usr/share/man:/opt/rh/ror40/root/usr/share/man:/opt/rh/v8314/root/usr/share/man:/opt/rh/nodejs010/root/usr/share/man: \
LIBRARY_PATH=/opt/rh/v8314/root/usr/lib64:/opt/rh/v8314/root/usr/lib64 \
X_SCLS=nodejs010 ror40 v8314 \
LD_LIBRARY_PATH=/opt/rh/v8314/root/usr/lib64:/opt/rh/ruby200/root/usr/lib64:/opt/rh/ror40/root/usr/lib64:/opt/rh/v8314/root/usr/lib64:/opt/rh/nodejs010/root/usr/lib64 \
CPATH=/opt/rh/v8314/root/usr/include:/opt/rh/v8314/root/usr/include \
PATH=/opt/rh/v8314/root/usr/bin:/opt/rh/ruby200/root/usr/bin:/opt/rh/ror40/root/usr/bin:/opt/rh/v8314/root/usr/bin:/opt/rh/nodejs010/root/usr/bin:/usr/local/bin:/usr/bin \
PYTHONPATH=/opt/rh/v8314/root/usr/lib/python2.7/site-packages:/opt/rh/v8314/root/usr/lib/python2.7/site-packages:/opt/rh/nodejs010/root/usr/lib/python2.7/site-packages \
GEM_PATH=/opt/rh/ror40/root/usr/share/gems:/opt/app-root/src/.gem/ruby:/opt/rh/ruby200/root/usr/share/gems:/opt/rh/ruby200/root/usr/local/share/gems \
PKG_CONFIG_PATH=/opt/rh/v8314/root/usr/lib64/pkgconfig:/opt/rh/ruby200/root/usr/lib64/pkgconfig:/opt/rh/ror40/root/usr/lib64/pkgconfig:/opt/rh/v8314/root/usr/lib64/pkgconfig
# -- end of generated instruction --
```2. (Optional) You may want to redirect the output straight into a Dockerfile:
```
envdiff -o docker scl openshift/ruby-20-centos7 >> Dockerfile
```If you want to print the environment in shell format, omit the `-o docker` flag:
```console
$ envdiff scl openshift/python-34-centos7
# scl enable rh-python34
MANPATH=/opt/rh/rh-python34/root/usr/share/man:
X_SCLS=rh-python34
LD_LIBRARY_PATH=/opt/rh/rh-python34/root/usr/lib64
PATH=/opt/rh/rh-python34/root/usr/bin:/usr/local/bin:/usr/bin
XDG_DATA_DIRS=/opt/rh/rh-python34/root/usr/share
PKG_CONFIG_PATH=/opt/rh/rh-python34/root/usr/lib64/pkgconfig
```### How does the scl mode works?
What is `envdiff` doing to generate an environment that transforms an initial
environment into one with collections enabled?
You can go read the code, it's all in the `scl.go` file, or follow along.First, we need to discover what collections are installed. This can be
accomplished with `scl --list` in a container.Second, we need two environments: one without any collections enabled, and
another one will all collections enabled.To get a clean environment, we run `bash -c env` in a temporary container. We
wrap the call to `env` in a Bash shell to be closer to what we get by enabling
collections. To make sure that the environment is clean no matter what is in the
image, we unset all environment variables set in the image when creating a
container.To get the environment with all collections enabled, it is `scl enable
collection1 collection2 ... env`. In other words, we run `env` to dump the
environment with all collections from the first step being enabled. Since `scl`
has a shebang that points to `/bin/bash`, this time we don't wrap the `env` call
like in the previous step.The last step is to do what `envdiff` is made to do: compare two environments.
Producing output as a Dockerfile ENV instruction makes it convenient to modify
existing Dockerfiles to permanently enable collections.