debianization and a wrapper program for /usr/bin

This commit is contained in:
Joey Hess 2014-04-03 00:59:26 -04:00
parent 167609746d
commit 42f207232b
13 changed files with 265 additions and 51 deletions

View File

@ -1,20 +1,30 @@
run: build CABAL?=cabal
run: deps build
./propellor ./propellor
dev: build tags dev: build tags
build: deps dist/setup-config build: dist/setup-config
if ! cabal build; then cabal configure; cabal build; fi if ! $(CABAL) build; then $(CABAL) configure; $(CABAL) build; fi
ln -sf dist/build/propellor/propellor ln -sf dist/build/config/config propellor
deps: deps:
@if [ $$(whoami) = root ]; then apt-get -y install gnupg ghc cabal-install libghc-missingh-dev libghc-ansi-terminal-dev libghc-ifelse-dev libghc-unix-compat-dev libghc-hslogger-dev libghc-network-dev libghc-async-dev; fi || true @if [ $$(whoami) = root ]; then apt-get -y install gnupg ghc cabal-install libghc-missingh-dev libghc-ansi-terminal-dev libghc-ifelse-dev libghc-unix-compat-dev libghc-hslogger-dev libghc-network-dev libghc-async-dev; fi || true
dist/setup-config: propellor.cabal dist/setup-config: propellor.cabal
cabal configure if [ "$(CABAL)" = ./Setup ]; then ghc --make Setup; fi
$(CABAL) configure
install:
install -d $(DESTDIR)/usr/bin $(DESTDIR)/usr/src/propellor
install -s dist/build/propellor/propellor $(DESTDIR)/usr/bin
$(CABAL) sdist
cat dist/propellor-*.tar.gz | \
(cd $(DESTDIR)/usr/src/propellor && tar zx --strip-components=1)
clean: clean:
rm -rf dist Setup tags propellor privdata/local rm -rf dist Setup tags propellor propellor-wrapper privdata/local
find -name \*.o -exec rm {} \; find -name \*.o -exec rm {} \;
find -name \*.hi -exec rm {} \; find -name \*.hi -exec rm {} \;
@ -22,4 +32,9 @@ clean:
tags: tags:
find . | grep -v /.git/ | grep -v /tmp/ | grep -v /dist/ | grep -v /doc/ | egrep '\.hs$$' | xargs hothasktags > tags 2>/dev/null find . | grep -v /.git/ | grep -v /tmp/ | grep -v /dist/ | grep -v /doc/ | egrep '\.hs$$' | xargs hothasktags > tags 2>/dev/null
# Upload to hackage.
hackage:
@cabal sdist
@cabal upload dist/*.tar.gz
.PHONY: tags .PHONY: tags

View File

@ -74,9 +74,10 @@ defaultMain getprops = do
headMaybe $ catMaybes $ map (\get -> get host) getprops headMaybe $ catMaybes $ map (\get -> get host) getprops
unknownhost :: HostName -> IO a unknownhost :: HostName -> IO a
unknownhost h = errorMessage $ unwords unknownhost h = errorMessage $ unlines
[ "Unknown host:", h [ "Unknown host: " ++ h
, "(perhaps you should specify the real hostname on the command line?)" , "(Perhaps you should specify the real hostname on the command line?)"
, "(Or, edit propellor's config.hs to configure this host)"
] ]
buildFirst :: CmdLine -> IO () -> IO () buildFirst :: CmdLine -> IO () -> IO ()

View File

@ -1,18 +1,18 @@
This is a work in progress configuration management system using Haskell This is a configuration management system using Haskell and Git.
and Git.
Propellor enures that the system it's run in satisfies a list of Propellor enures that the system it's run against satisfies a list of
properties, taking action as necessary when a property is not yet met. properties, taking action as necessary when a property is not yet met.
The design is intentionally very minimal. Propellor is configured via a git repository, which typically lives
in ~/.propellor/. The git repository contains a config.hs file,
and also the entire source code to propellor.
Propellor lives in a git repository. You'll typically want to have You typically want to have the repository checked out on a laptop, in order
the repository checked out on a laptop, in order to make changes and push to make changes and push them out to hosts. Each host will also have a
them out to hosts. Each host will also have a clone of the repository, clone of the repository, and in that clone "make" can be used to build and
and in that clone "make" can be used to build and run propellor. run propellor. This can be done by a cron job (which propellor can set up),
This can be done by a cron job (which propellor can set up), or a remote host can be triggered to update by running propellor on your
or a remote host can be triggered to update by running propellor laptop: propellor --spin $host
on your laptop: propellor --spin $host
Properties are defined using Haskell. Edit config.hs to get started. Properties are defined using Haskell. Edit config.hs to get started.
@ -28,35 +28,41 @@ and so it's easy to factor out things like classes of hosts as desired.
## quick start ## quick start
1. Clone propellor's git repository to your laptop (or whatever). 1. Get propellor installed
git clone git://git.kitenet.net/propellor `cabal install propellor`
or joeyh/propellor on github or
2. Run: sudo make deps # installs build dependencies `apt-get install propellor`
3. Run: make build 2. Run propellor for the first time. It will set up a `~/.propellor/` git
4. If you don't have a gpg private key, generate one: gpg --gen-key repository for you.
5. Run: ./propellor --add-key $KEYID 3. In `~/.propellor/`, use git to push the repository to a central
7. Pick a host and run: ./propellor --spin $HOST server (github, or your own git server). Configure that central
8. Now you have a simple propellor deployment, but it doesn't do anything server as the origin remote of the repository.
to the host yet, besides installing propellor. 4. If you don't have a gpg private key, generate one: `gpg --gen-key`
5. Run: `propellor --add-key $KEYID`
6. Edit `~/.propellor/config.hs`, and add a host you want to manage.
You can start by not adding any properties, or only a few.
7. Pick a host and run: `propellor --spin $HOST`
8. Now you have a simple propellor deployment, but it doesn't do
much to the host yet, besides installing propellor.
So, edit config.hs to configure the host (maybe start with a few simple So, edit `~/.propellor/config.hs` to configure the host (maybe
properties), and re-run step 7. Repeat until happy and move on to the start with a few simple properties), and re-run step 7.
next host. :) Repeat until happy and move on to the next host. :)
9. To move beyond manually running propellor --spin against hosts 9. To move beyond manually running propellor --spin against hosts
when you change configuration, add a property to your hosts when you change configuration, add a property to your hosts
like: Cron.runPropellor "30 * * * *" like: `Cron.runPropellor "30 * * * *"`
Now they'll automatically update every 30 minutes, and you can Now they'll automatically update every 30 minutes, and you can
`git commit -S` and `git push` changes that affect any number of `git commit -S` and `git push` changes that affect any number of
hosts. hosts.
10. Write some neat new properties and send patches to propellor@joeyh.name! 8. Write some neat new properties and send patches to <propellor@joeyh.name>!
## security ## security
Propellor's security model is that the hosts it's used to deploy are Propellor's security model is that the hosts it's used to deploy are
untrusted, and that the central git repository server is untrusted. untrusted, and that the central git repository server is untrusted.
The only trusted machine is the laptop where you run propellor --spin The only trusted machine is the laptop where you run `propellor --spin`
to connect to a remote host. And that one only because you have a ssh key to connect to a remote host. And that one only because you have a ssh key
or login password to the host. or login password to the host.
@ -70,10 +76,10 @@ otherwise.
That is only done when privdata/keyring.gpg exists. To set it up: That is only done when privdata/keyring.gpg exists. To set it up:
gpg --gen-key # only if you don't already have a gpg key gpg --gen-key # only if you don't already have a gpg key
propellor --add-key $MYKEYID propellor --add-key $MYKEYID
In order to be secure from the beginning, when propellor --spin is used In order to be secure from the beginning, when `propellor --spin` is used
to bootstrap propellor on a new host, it transfers the local git repositry to bootstrap propellor on a new host, it transfers the local git repositry
to the remote host over ssh. After that, the remote host knows the to the remote host over ssh. After that, the remote host knows the
gpg key, and will use it to verify git fetches. gpg key, and will use it to verify git fetches.
@ -81,17 +87,17 @@ gpg key, and will use it to verify git fetches.
Since the propoellor git repository is public, you can't store Since the propoellor git repository is public, you can't store
in cleartext private data such as passwords, ssh private keys, etc. in cleartext private data such as passwords, ssh private keys, etc.
Instead, propellor --spin $host looks for a privdata/$host.gpg file and Instead, `propellor --spin $host` looks for a `~/.propellor/privdata/$host.gpg` file and
if found decrypts it and sends it to the remote host using ssh. This lets if found decrypts it and sends it to the remote host using ssh. This lets
a remote host know its own private data, without seeing all the rest. a remote host know its own private data, without seeing all the rest.
To securely store private data, use: propellor --set $host $field To securely store private data, use: `propellor --set $host $field`
The field name will be something like 'Password "root"'; see PrivData.hs The field name will be something like 'Password "root"'; see PrivData.hs
for available fields. for available fields.
## debugging ## debugging
Set PROPELLOR_DEBUG=1 to make propellor print out all the commands it runs Set `PROPELLOR_DEBUG=1` to make propellor print out all the commands it runs
and any other debug messages Properties choose to emit. and any other debug messages that Properties choose to emit.
[1] http://reclass.pantsfullofunix.net/ [1] http://reclass.pantsfullofunix.net/

8
debian/changelog vendored
View File

@ -1,4 +1,10 @@
propellor (0.2) unstable; urgency=low propellor (0.2.1) unstable; urgency=medium
* First release with Debian package.
-- Joey Hess <joeyh@debian.org> Thu, 03 Apr 2014 01:43:14 -0400
propellor (0.2.0) unstable; urgency=low
* Added support for provisioning Docker containers. * Added support for provisioning Docker containers.
* Bootstrap deployment now pushes the git repo to the remote host * Bootstrap deployment now pushes the git repo to the remote host

1
debian/compat vendored Normal file
View File

@ -0,0 +1 @@
9

36
debian/control vendored Normal file
View File

@ -0,0 +1,36 @@
Source: propellor
Section: admin
Priority: optional
Build-Depends:
debhelper (>= 9),
ghc (>= 7.4),
cabal-install,
libghc-async-dev,
libghc-missingh-dev,
libghc-hslogger-dev,
libghc-unix-compat-dev,
libghc-ansi-terminal-dev,
libghc-ifelse-dev,
Maintainer: Joey Hess <joeyh@debian.org>
Standards-Version: 3.9.5
Vcs-Git: git://git.kitenet.net/propellor
Homepage: http://joeyh.name/code/propellor/
Package: propellor
Architecture: any
Section: admin
Depends: ${misc:Depends}, ${shlibs:Depends},
ghc (>= 7.4),
cabal-install,
libghc-async-dev,
libghc-missingh-dev,
libghc-hslogger-dev,
libghc-unix-compat-dev,
libghc-ansi-terminal-dev,
libghc-ifelse-dev,
git,
Description: property-based host configuration management in haskell
Propellor enures that the system it's run in satisfies a list of
properties, taking action as necessary when a property is not yet met.
.
It is configured using haskell.

11
debian/copyright vendored Normal file
View File

@ -0,0 +1,11 @@
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Source: native package
Files: *
Copyright: © 2010-2014 Joey Hess <joey@kitenet.net>
License: GPL-3+
License: GPL-3+
The full text of version 3 of the GPL is distributed as GPL in
this package's source, or in /usr/share/common-licenses/GPL-3 on
Debian systems.

3
debian/lintian-overrides vendored Normal file
View File

@ -0,0 +1,3 @@
# These files are used in a git repository that propellor sets up.
propellor: package-contains-vcs-control-file usr/src/propellor/.gitignore
propellor: extra-license-file usr/src/propellor/GPL

15
debian/propellor.1 vendored Normal file
View File

@ -0,0 +1,15 @@
.\" -*- nroff -*-
.TH propellor 1 "Commands"
.SH NAME
propellor \- property-based host configuration management in haskell
.SH SYNOPSIS
.B propellor [options] host
.SH DESCRIPTION
.I propellor
is a property-based host configuration management program written
and configured in haskell.
.PP
The first time you run propellor, it will set up a ~/.propellor/
repository. Edit ~/.propellor/config.hs to configure it.
.SH AUTHOR
Joey Hess <joey@kitenet.net>

14
debian/rules vendored Executable file
View File

@ -0,0 +1,14 @@
#!/usr/bin/make -f
# Avoid using cabal, as it writes to $HOME
export CABAL=./Setup
%:
dh $@
override_dh_auto_build:
$(MAKE) build
override_dh_installdocs:
dh_installdocs README.md TODO
override_dh_installman:
dh_installman debian/propellor.1

View File

@ -1,5 +1,5 @@
Name: propellor Name: propellor
Version: 0.2.0 Version: 0.2.1
Cabal-Version: >= 1.6 Cabal-Version: >= 1.6
License: GPL License: GPL
Maintainer: Joey Hess <joey@kitenet.net> Maintainer: Joey Hess <joey@kitenet.net>
@ -14,20 +14,35 @@ Extra-Source-Files:
README.md README.md
TODO TODO
CHANGELOG CHANGELOG
simple-config.hs
Makefile Makefile
debian/changelog debian/changelog
debian/README debian/README.Debian
simple-config.hs debian/propellor.1
debian/compat
debian/control
debian/copyright
debian/rules
debian/lintian-overrides
.gitignore
Synopsis: property-based host configuration management in haskell Synopsis: property-based host configuration management in haskell
Description: Description:
Propellor enures that the system it's run in satisfies a list of Propellor enures that the system it's run in satisfies a list of
properties, taking action as necessary when a property is not yet met. properties, taking action as necessary when a property is not yet met.
. .
While Propellor can be installed from hackage, to customize and use it It is configured using haskell.
you should fork its git repository and modify it from there:
git clone git://git.kitenet.net/propellor
Executable propellor Executable propellor
Main-Is: propellor.hs
GHC-Options: -Wall
Build-Depends: MissingH, directory, filepath, base >= 4.5, base < 5,
IfElse, process, bytestring, hslogger, unix-compat, ansi-terminal,
containers, network, async
if (! os(windows))
Build-Depends: unix
Executable config
Main-Is: config.hs Main-Is: config.hs
GHC-Options: -Wall -threaded GHC-Options: -Wall -threaded
Build-Depends: MissingH, directory, filepath, base >= 4.5, base < 5, Build-Depends: MissingH, directory, filepath, base >= 4.5, base < 5,
@ -38,7 +53,7 @@ Executable propellor
Build-Depends: unix Build-Depends: unix
Library Library
GHC-Options: -Wall -threaded GHC-Options: -Wall
Build-Depends: MissingH, directory, filepath, base >= 4.5, base < 5, Build-Depends: MissingH, directory, filepath, base >= 4.5, base < 5,
IfElse, process, bytestring, hslogger, unix-compat, ansi-terminal, IfElse, process, bytestring, hslogger, unix-compat, ansi-terminal,
containers, network, async containers, network, async

91
propellor.hs Normal file
View File

@ -0,0 +1,91 @@
-- | Wrapper program for propellor distribution.
--
-- Distributions should install this program into PATH.
-- (Cabal builds it as dict/build/propellor.
--
-- This is not the propellor main program (that's config.hs)
--
-- This installs propellor's source into ~/.propellor,
-- uses it to build the real propellor program (if not already built),
-- and runs it.
--
-- The source is either copied from /usr/src/propellor, or is cloned from
-- git over the network.
import Utility.UserInfo
import Utility.Monad
import Utility.Process
import Utility.SafeCommand
import Utility.Directory
import Control.Monad
import Control.Monad.IfElse
import System.Directory
import System.FilePath
import System.Environment (getArgs)
import System.Exit
import System.Posix.Directory
srcdir :: FilePath
srcdir = "/usr/src/propellor"
-- Using the github mirror of the main propellor repo because
-- it is accessible over https for better security.
srcrepo :: String
srcrepo = "https://github.com/joeyh/propellor.git"
main :: IO ()
main = do
args <- getArgs
home <- myHomeDir
let propellordir = home </> ".propellor"
let propellorbin = propellordir </> "propellor"
wrapper args propellordir propellorbin
wrapper :: [String] -> FilePath -> FilePath -> IO ()
wrapper args propellordir propellorbin = do
unlessM (doesDirectoryExist propellordir) $
makeRepo
buildruncfg
where
chain = do
(_, _, _, pid) <- createProcess (proc propellorbin args)
exitWith =<< waitForProcess pid
makeRepo = do
putStrLn $ "Setting up your propellor repo in " ++ propellordir
putStrLn ""
ifM (doesDirectoryExist srcdir)
( do
void $ boolSystem "cp" [Param "-a", File srcdir, File propellordir]
changeWorkingDirectory propellordir
void $ boolSystem "git" [Param "init"]
void $ boolSystem "git" [Param "add", Param "."]
setuprepo True
, do
void $ boolSystem "git" [Param "clone", Param srcrepo, File propellordir]
void $ boolSystem "git" [Param "remote", Param "rm", Param "origin"]
setuprepo False
)
setuprepo fromsrcdir = do
changeWorkingDirectory propellordir
whenM (doesDirectoryExist "privdata") $
mapM_ nukeFile =<< dirContents "privdata"
void $ boolSystem "git" [Param "commit", Param "--allow-empty", Param "--quiet", Param "-m", Param "setting up propellor git repository"]
void $ boolSystem "git" [Param "remote", Param "add", Param "upstream", Param srcrepo]
-- Connect synthetic git repo with upstream history so
-- merging with upstream will work going forward.
-- Note -s outs is used to avoid getting any divergent
-- changes from upstream.
when fromsrcdir $ do
void $ boolSystem "git" [Param "fetch", Param "upstream"]
version <- readProcess "dpkg-query" ["--showformat", "${Version}", "--show", "propellor"]
void $ boolSystem "git" [Param "merge", Param "-s", Param "ours", Param version]
buildruncfg = do
changeWorkingDirectory propellordir
ifM (boolSystem "make" [Param "build"])
( do
putStrLn ""
putStrLn ""
chain
, error "Propellor build failed."
)