Merge lp:~abentley/charms/precise/charmworld/auto-production into lp:~juju-jitsu/charms/precise/charmworld/trunk

Proposed by Aaron Bentley
Status: Merged
Merged at revision: 34
Proposed branch: lp:~abentley/charms/precise/charmworld/auto-production
Merge into: lp:~juju-jitsu/charms/precise/charmworld/trunk
Diff against target: 183 lines (+112/-12)
7 files modified
common (+3/-5)
hooks/config-changed (+3/-4)
hooks/database-relation-broken (+1/-1)
hooks/database-relation-changed (+1/-1)
production_overrides.ini (+46/-0)
revision (+1/-1)
write_config.py (+57/-0)
To merge this branch: bzr merge lp:~abentley/charms/precise/charmworld/auto-production
Reviewer Review Type Date Requested Status
Juju-Jitsu Hackers Pending
Review via email: mp+145420@code.launchpad.net

Description of the change

Auto-generate production.ini

production.ini is now auto-generated from
1. defaults
2. overrides
3. specific settings from any existing production.ini (session.secret,
   mongo.port, mongo.host)
4. juju environment

Once production.ini is removed from the source tree, this will minimize the
chance of conflicts while ensuring production.ini is up-to-date with the
defaults.

https://codereview.appspot.com/7229057/

To post a comment you must log in.
Revision history for this message
Richard Harding (rharding) wrote :

lgtm

I wonder a little bit if we can reuse the configparser merging code abel
has in charmworld/lib/config, but I suppose it's different enough since
this code also has field limitations defined on what can be overridden.

Should there be some documentation around to help aid other people
working on the charm on how the parts fit together? If we handed this to
abel or jc would it be clear how the ini was generated and used in
production?

https://codereview.appspot.com/7229057/

Revision history for this message
Aaron Bentley (abentley) wrote :

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 13-01-29 11:11 AM, <email address hidden> wrote:
> I wonder a little bit if we can reuse the configparser merging code
> abel has in charmworld/lib/config

The code in charmworld/lib/config doesn't do the merging, it delegates
that to ConfigParser.read, the same as mine does.

The bulk of charmworld/lib/config.py is concerned with emitting
warnings when sections and options are used in the override that are
not present in the default. However, this does not indicate a
problem. For example, the "logger_exc_logger" section in
production_overrides.ini is entirely legitimate, and it would be
inappropriate in the default, because the default logging
configuration is different. So that code is not useful in this context.

If I wanted to use Abel's script anyhow, it would need to take 3
inputs: defaults, production overrides, local configuration. Since it
doesn't, it's not useful here. If it did, I'd still need a Python
script. It would use ConfigParser to write out a temporary config for
local configuration.

> Should there be some documentation around to help aid other people
> working on the charm on how the parts fit together?

To me, the ideal is that the code is clear enough that documentation
is superfluous. I'm not sure whether we've reached that here.

Aaron
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with undefined - http://www.enigmail.net/

iEYEARECAAYFAlEH+NgACgkQ0F+nu1YWqI2TVwCghD7+Rvvcornf81vhFAJZIlwR
TicAn1rcTH29iQ5IRO8yOfwfKjzD63iD
=8cOq
-----END PGP SIGNATURE-----

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'common'
2--- common 2013-01-10 20:38:14 +0000
3+++ common 2013-01-29 15:55:29 +0000
4@@ -1,8 +1,6 @@
5 project_dir="/home/ubuntu/charmworld"
6 CONFIG_FILE="$project_dir/production.ini"
7-configure_mongo(){
8- db_host=${1-}
9- db_port=${2-}
10- sed -i -e "s/mongo.host =.*/mongo.host = ${db_host}/" \
11- -e "s/mongo.port =.*/mongo.port = ${db_port}/" $CONFIG_FILE
12+configure(){
13+ ./write_config.py $project_dir/default.ini production_overrides.ini\
14+ $CONFIG_FILE "$@"
15 }
16
17=== modified file 'hooks/config-changed'
18--- hooks/config-changed 2013-01-24 17:34:53 +0000
19+++ hooks/config-changed 2013-01-29 15:55:29 +0000
20@@ -33,6 +33,9 @@
21 make clean
22 make install
23 pip install pyramid_exclog
24+ cd $old_dir
25+ configure
26+ cd $project_dir
27 chown ubuntu.ubuntu . -R
28 if grep -E 'mongo.host = .+' $CONFIG_FILE; then
29 INI=$CONFIG_FILE bin/migrations upgrade
30@@ -51,10 +54,6 @@
31 update_source
32 fi
33
34-secret=$(head -c 3 /dev/urandom|sha1sum|cut -f 1 -d ' ')
35-# Supply secret, if unspecified.
36-sed -i -e "s/session.secret =$/session.secret = ${secret}/" $CONFIG_FILE
37-
38 interval=`config-get execute-ingest-every`
39 : ${interval:-0}
40
41
42=== modified file 'hooks/database-relation-broken'
43--- hooks/database-relation-broken 2013-01-10 20:19:05 +0000
44+++ hooks/database-relation-broken 2013-01-29 15:55:29 +0000
45@@ -4,4 +4,4 @@
46 hooks/stop || true
47 source common
48
49-configure_mongo
50+configure '' ''
51
52=== modified file 'hooks/database-relation-changed'
53--- hooks/database-relation-changed 2013-01-24 17:34:53 +0000
54+++ hooks/database-relation-changed 2013-01-29 15:55:29 +0000
55@@ -18,7 +18,7 @@
56 relation_port=`relation-get port`
57 DB_PORT=${relation_port:-27017}
58
59-configure_mongo $DB_HOST $DB_PORT
60+configure $DB_HOST $DB_PORT
61
62 INI=$CONFIG_FILE $project_dir/bin/migrations upgrade --init
63
64
65=== added file 'production_overrides.ini'
66--- production_overrides.ini 1970-01-01 00:00:00 +0000
67+++ production_overrides.ini 2013-01-29 15:55:29 +0000
68@@ -0,0 +1,46 @@
69+[app:main]
70+pyramid.debug_templates = false
71+pyramid.includes = pyramid_exclog
72+pyramid.reload_templates = false
73+mongo.host =
74+mongo.port =
75+session.secret =
76+
77+[server:main]
78+port = 6543
79+
80+[loggers]
81+keys = root, charmworld, exc_logger
82+
83+[handlers]
84+keys = console, filelog
85+
86+[formatters]
87+keys = generic, exception
88+
89+[logger_root]
90+level = WARN
91+
92+handlers = console, filelog
93+[logger_charmworld]
94+level = WARN
95+
96+[logger_exc_logger]
97+level = ERROR
98+handlers =
99+qualname = exc_logger
100+
101+[handler_filelog]
102+class = FileHandler
103+args = ('/home/ubuntu/var/app.log', 'a')
104+level = INFO
105+formatter = generic
106+
107+[handler_exc_handler]
108+class = StreamHandler
109+args = (sys.stderr,)
110+level = ERROR
111+formatter = exc_formatter
112+
113+[formatter_exception]
114+format = %(asctime)s %(message)s
115
116=== modified file 'revision'
117--- revision 2013-01-24 17:34:53 +0000
118+++ revision 2013-01-29 15:55:29 +0000
119@@ -1,1 +1,1 @@
120-17
121+18
122
123=== added file 'write_config.py'
124--- write_config.py 1970-01-01 00:00:00 +0000
125+++ write_config.py 2013-01-29 15:55:29 +0000
126@@ -0,0 +1,57 @@
127+#!/usr/bin/env python
128+
129+from ConfigParser import ConfigParser, NoSectionError
130+from random import getrandbits
131+import sys
132+
133+
134+def update_config(parser, items):
135+ configurable = set(['session.secret', 'mongo.host', 'mongo.port'])
136+ for key, value in items:
137+ if key not in configurable:
138+ continue
139+ parser.set('app:main', key, value)
140+
141+
142+def read_config(files):
143+ new_config = ConfigParser()
144+ new_config.read(files)
145+ return new_config
146+
147+
148+def write_new_config(changes, default, override, target):
149+ new_config = read_config([default, override])
150+ old_config = read_config(target)
151+ try:
152+ update_config(new_config, old_config.items('app:main', raw=True))
153+ except NoSectionError:
154+ pass
155+ update_config(new_config, changes)
156+ if new_config.get('app:main', 'session.secret') == '':
157+ new_config.set('app:main', 'session.secret', str(getrandbits(32)))
158+ with open(target, 'w') as output:
159+ new_config.write(output)
160+
161+
162+class UsageError(Exception):
163+ """An error triggered by incorrect usage"""
164+
165+
166+def main():
167+ if len(sys.argv) < 4:
168+ raise UsageError('Usage: %s DEFAULTS OVERRIDES TARGET [HOST [PORT]]')
169+ changes = {}
170+ if len(sys.argv) > 4:
171+ changes['mongo.host'] = sys.argv[4]
172+ if len(sys.argv) > 5:
173+ changes['mongo.port'] = sys.argv[5]
174+ parser = write_new_config(changes.items(), default=sys.argv[1],
175+ override=sys.argv[2], target=sys.argv[3])
176+
177+
178+if __name__ == '__main__':
179+ try:
180+ main()
181+ except UsageError as e:
182+ sys.stderr.write(str(e))
183+ sys.exit(1)

Subscribers

People subscribed via source and target branches

to all changes: