summaryrefslogtreecommitdiff
path: root/puppet/modules/couchdb/files
diff options
context:
space:
mode:
Diffstat (limited to 'puppet/modules/couchdb/files')
-rwxr-xr-xpuppet/modules/couchdb/files/Debian/couchdb160
-rw-r--r--puppet/modules/couchdb/files/couch-doc-diff17
-rw-r--r--puppet/modules/couchdb/files/couch-doc-update219
-rw-r--r--puppet/modules/couchdb/files/local.ini84
4 files changed, 480 insertions, 0 deletions
diff --git a/puppet/modules/couchdb/files/Debian/couchdb b/puppet/modules/couchdb/files/Debian/couchdb
new file mode 100755
index 00000000..ccdfe716
--- /dev/null
+++ b/puppet/modules/couchdb/files/Debian/couchdb
@@ -0,0 +1,160 @@
+#!/bin/sh -e
+
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy of
+# the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+### BEGIN INIT INFO
+# Provides: couchdb
+# Required-Start: $local_fs $remote_fs
+# Required-Stop: $local_fs $remote_fs
+# Default-Start: 2 3 4 5
+# Default-Stop: 0 1 6
+# Short-Description: Apache CouchDB init script
+# Description: Apache CouchDB init script for the database server.
+### END INIT INFO
+
+SCRIPT_OK=0
+SCRIPT_ERROR=1
+
+DESCRIPTION="database server"
+NAME=couchdb
+SCRIPT_NAME=`basename $0`
+COUCHDB=/usr/bin/couchdb
+CONFIGURATION_FILE=/etc/default/couchdb
+RUN_DIR=/var/run/couchdb
+LSB_LIBRARY=/lib/lsb/init-functions
+
+if test ! -x $COUCHDB; then
+ exit $SCRIPT_ERROR
+fi
+
+if test -r $CONFIGURATION_FILE; then
+ . $CONFIGURATION_FILE
+fi
+
+log_daemon_msg () {
+ # Dummy function to be replaced by LSB library.
+
+ echo $@
+}
+
+log_end_msg () {
+ # Dummy function to be replaced by LSB library.
+
+ if test "$1" != "0"; then
+ echo "Error with $DESCRIPTION: $NAME"
+ fi
+ return $1
+}
+
+if test -r $LSB_LIBRARY; then
+ . $LSB_LIBRARY
+fi
+
+run_command () {
+ command="$1"
+ if test -n "$COUCHDB_OPTIONS"; then
+ command="$command $COUCHDB_OPTIONS"
+ fi
+ if test -n "$COUCHDB_USER"; then
+ if su $COUCHDB_USER -c "$command"; then
+ return $SCRIPT_OK
+ else
+ return $SCRIPT_ERROR
+ fi
+ else
+ if $command; then
+ return $SCRIPT_OK
+ else
+ return $SCRIPT_ERROR
+ fi
+ fi
+}
+
+start_couchdb () {
+ # Start Apache CouchDB as a background process.
+
+ mkdir -p "$RUN_DIR"
+ chown -R "$COUCHDB_USER" "$RUN_DIR"
+ command="$COUCHDB -b"
+ if test -n "$COUCHDB_STDOUT_FILE"; then
+ command="$command -o $COUCHDB_STDOUT_FILE"
+ fi
+ if test -n "$COUCHDB_STDERR_FILE"; then
+ command="$command -e $COUCHDB_STDERR_FILE"
+ fi
+ if test -n "$COUCHDB_RESPAWN_TIMEOUT"; then
+ command="$command -r $COUCHDB_RESPAWN_TIMEOUT"
+ fi
+ run_command "$command" > /dev/null
+}
+
+stop_couchdb () {
+ # Stop the running Apache CouchDB process.
+
+ run_command "$COUCHDB -d" > /dev/null
+ pkill -u couchdb
+ # always return true even if no remaining couchdb procs got killed
+ /bin/true
+}
+
+display_status () {
+ # Display the status of the running Apache CouchDB process.
+
+ run_command "$COUCHDB -s"
+}
+
+parse_script_option_list () {
+ # Parse arguments passed to the script and take appropriate action.
+
+ case "$1" in
+ start)
+ log_daemon_msg "Starting $DESCRIPTION" $NAME
+ if start_couchdb; then
+ log_end_msg $SCRIPT_OK
+ else
+ log_end_msg $SCRIPT_ERROR
+ fi
+ ;;
+ stop)
+ log_daemon_msg "Stopping $DESCRIPTION" $NAME
+ if stop_couchdb; then
+ log_end_msg $SCRIPT_OK
+ else
+ log_end_msg $SCRIPT_ERROR
+ fi
+ ;;
+ restart|force-reload)
+ log_daemon_msg "Restarting $DESCRIPTION" $NAME
+ if stop_couchdb; then
+ if start_couchdb; then
+ log_end_msg $SCRIPT_OK
+ else
+ log_end_msg $SCRIPT_ERROR
+ fi
+ else
+ log_end_msg $SCRIPT_ERROR
+ fi
+ ;;
+ status)
+ display_status
+ ;;
+ *)
+ cat << EOF >&2
+Usage: $SCRIPT_NAME {start|stop|restart|force-reload|status}
+EOF
+ exit $SCRIPT_ERROR
+ ;;
+ esac
+}
+
+parse_script_option_list $@
diff --git a/puppet/modules/couchdb/files/couch-doc-diff b/puppet/modules/couchdb/files/couch-doc-diff
new file mode 100644
index 00000000..a5907d5e
--- /dev/null
+++ b/puppet/modules/couchdb/files/couch-doc-diff
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+# Run a diff between a couch document specified as the first parameter
+# and the second parameter.
+# Diff returns 0 if there is no difference. This way you can tell the data
+# is already on the couch.
+# Both the couch document and the second paramter will be pretty printed
+# before comparison so differences in spaces etc. do not matter.
+# All keys starting with an underscore on the couch such as _id and _rev
+# will be removed before the comparison - we assume we want to compare
+# the real data, not the metadata about the document as we usually do not
+# know or care about what the id and revision will be.
+
+curl -s --netrc-file /etc/couchdb/couchdb.netrc $1 \
+ | python -mjson.tool \
+ | grep -v '^\s*"_' \
+ | diff -w - <(echo $2 | python -mjson.tool)
diff --git a/puppet/modules/couchdb/files/couch-doc-update b/puppet/modules/couchdb/files/couch-doc-update
new file mode 100644
index 00000000..a137e7ff
--- /dev/null
+++ b/puppet/modules/couchdb/files/couch-doc-update
@@ -0,0 +1,219 @@
+#!/usr/bin/ruby
+require 'syslog'
+
+#
+# This script will delete or update the values of a particular couchdb document. The benefit of this little script over
+# using a simple curl command for updating a document is this:
+#
+# * exit non-zero status if document was not updated.
+# * updates existing documents easily, taking care of the _rev id for you.
+# * if document doesn't exist, it is created
+#
+# REQUIREMENTS
+#
+# gem 'couchrest'
+#
+# USAGE
+#
+# see the ouput of
+#
+# couch-doc-update
+#
+# the content of <file> will be merged with the data provided.
+# If you only want the file content use --data '{}'
+#
+# EXAMPLE
+#
+# create a new user:
+# couch-doc-update --db _users --id org.couchdb.user:ca_daemon --data '{"type": "user", "name": "ca_daemon", "roles": ["certs"], "password": "sshhhh"}'
+#
+# update a user:
+# couch-doc-update --db _users --id org.couchdb.user:ca_daemon --data '{"password":"sssshhh"}'
+#
+# To update the _users DB on bigcouch, you must connect to port 5986 instead of the default couchdb port 5984
+#
+# delete a doc:
+# couch-doc-update --delete --db invite_codes --id dfaf0ee65670c16d5a9161dc86f3bff8
+#
+
+begin; require 'rubygems'; rescue LoadError; end # optionally load rubygems
+require 'couchrest'
+
+def main
+ db, id, data, delete = process_options
+
+ result = if delete
+ delete_document(db, id)
+ else
+ set_document(db, id, data)
+ end
+
+ exit 0 if result['ok']
+ raise StandardError.new(result.inspect)
+rescue StandardError => exc
+ db_without_password = db.to_s.sub(/:[^\/]*@/, ':PASSWORD_HIDDEN@')
+ indent = " "
+ log "ERROR: " + exc.to_s
+ log indent + $@[0..4].join("\n#{indent}")
+ log indent + "Failed writing to #{db_without_password}/#{id}"
+ exit 1
+end
+
+def log(message)
+ $stderr.puts message
+ Syslog.open('couch-doc-update') do |logger|
+ logger.log(Syslog::LOG_CRIT, message)
+ end
+end
+
+def process_options
+ #
+ # parse options
+ #
+ host = nil
+ db_name = nil
+ doc_id = nil
+ new_data = nil
+ filename = nil
+ netrc_file = nil
+ delete = false
+ loop do
+ case ARGV[0]
+ when '--host' then ARGV.shift; host = ARGV.shift
+ when '--db' then ARGV.shift; db_name = ARGV.shift
+ when '--id' then ARGV.shift; doc_id = ARGV.shift
+ when '--data' then ARGV.shift; new_data = ARGV.shift
+ when '--file' then ARGV.shift; filename = ARGV.shift
+ when '--netrc-file' then ARGV.shift; netrc_file = ARGV.shift
+ when '--delete' then ARGV.shift; delete = true
+ when /^-/ then usage("Unknown option: #{ARGV[0].inspect}")
+ else break
+ end
+ end
+ usage("Missing required option") unless db_name && doc_id && (new_data || delete)
+
+ unless delete
+ new_data = MultiJson.load(new_data)
+ new_data.merge!(read_file(filename)) if filename
+ end
+ db = CouchRest.database(connection_string(db_name, host, netrc_file))
+ return db, doc_id, new_data, delete
+end
+
+def read_file(filename)
+ data = MultiJson.load( IO.read(filename) )
+ # strip off _id and _rev to avoid conflicts
+ data.delete_if {|k,v| k.start_with? '_'}
+end
+
+ #
+ # update document
+ #
+def set_document(db, id, data)
+ attempt ||= 1
+ doc = get_document(db, id)
+ if doc
+ doc.id ||= id
+ update_document(db, doc, data)
+ else
+ create_document(db, id, data)
+ end
+rescue RestClient::Conflict
+ # retry once, reraise if that does not work
+ raise if attempt > 1
+ attempt += 1
+ retry
+end
+
+COUCH_RESPONSE_OK = { 'ok' => true }
+
+# Deletes document, if exists, with retry
+def delete_document(db, id)
+ attempts ||= 1
+ doc = get_document(db, id)
+ if doc
+ db.delete_doc(doc)
+ else
+ COUCH_RESPONSE_OK
+ end
+rescue RestClient::ExceptionWithResponse => e
+ if attempts < 6 && !e.response.nil? && RETRY_CODES.include?(e.response.code)
+ attempts += 1
+ sleep 10
+ retry
+ else
+ raise e
+ end
+end
+
+def get_document(db, doc_id)
+ begin
+ db.get(doc_id)
+ rescue RestClient::ResourceNotFound
+ nil
+ end
+end
+
+# if the response status code is one of these
+# then retry instead of failing.
+RETRY_CODES = [500, 422].freeze
+
+def update_document(db, doc, data)
+ attempts ||= 1
+ doc.reject! {|k,v| !["_id", "_rev"].include? k}
+ doc.merge! data
+ db.save_doc(doc)
+rescue RestClient::ExceptionWithResponse => e
+ if attempts < 6 && !e.response.nil? && RETRY_CODES.include?(e.response.code)
+ attempts += 1
+ sleep 10
+ retry
+ else
+ raise e
+ end
+end
+
+def create_document(db, doc_id, data)
+ attempts ||= 1
+ data["_id"] = doc_id
+ db.save_doc(data)
+rescue RestClient::ExceptionWithResponse => e
+ if attempts < 6 && !e.response.nil? && RETRY_CODES.include?(e.response.code)
+ attempts += 1
+ sleep 10
+ retry
+ else
+ raise e
+ end
+end
+
+def connection_string(database, host, netrc_file = nil)
+ protocol = "http"
+ #hostname = "127.0.0.1"
+ port = "5984"
+ username = "admin"
+ password = ""
+
+ netrc = File.read(netrc_file || '/etc/couchdb/couchdb.netrc')
+ netrc.scan(/\w+ [\w\.]+/).each do |key_value|
+ key, value = key_value.split ' '
+ case key
+ when "machine" then host ||= value + ':' + port
+ when "login" then username = value
+ when "password" then password = value
+ end
+ end
+
+ host ||= '127.0.0.1:5984'
+
+ "%s://%s:%s@%s/%s" % [protocol, username, password, host, database]
+end
+
+def usage(s)
+ $stderr.puts(s)
+ $stderr.puts("Usage: #{File.basename($0)} --host <host> --db <db> --id <doc_id> --data <json> [--file <file>] [--netrc-file <netrc-file>]")
+ $stderr.puts(" #{File.basename($0)} --host <host> --db <db> --id <doc_id> --delete [--netrc-file <netrc-file>]")
+ exit(2)
+end
+
+main()
diff --git a/puppet/modules/couchdb/files/local.ini b/puppet/modules/couchdb/files/local.ini
new file mode 100644
index 00000000..7365b6c6
--- /dev/null
+++ b/puppet/modules/couchdb/files/local.ini
@@ -0,0 +1,84 @@
+; CouchDB Configuration Settings
+
+; Custom settings should be made in this file. They will override settings
+; in default.ini, but unlike changes made to default.ini, this file won't be
+; overwritten on server upgrade.
+
+[couchdb]
+;max_document_size = 4294967296 ; bytes
+
+[httpd]
+;port = 5984
+;bind_address = 127.0.0.1
+; Options for the MochiWeb HTTP server.
+;server_options = [{backlog, 128}, {acceptor_pool_size, 16}]
+; For more socket options, consult Erlang's module 'inet' man page.
+;socket_options = [{recbuf, 262144}, {sndbuf, 262144}, {nodelay, true}]
+
+; Uncomment next line to trigger basic-auth popup on unauthorized requests.
+;WWW-Authenticate = Basic realm="administrator"
+
+; Uncomment next line to set the configuration modification whitelist. Only
+; whitelisted values may be changed via the /_config URLs. To allow the admin
+; to change this value over HTTP, remember to include {httpd,config_whitelist}
+; itself. Excluding it from the list would require editing this file to update
+; the whitelist.
+;config_whitelist = [{httpd,config_whitelist}, {log,level}, {etc,etc}]
+
+[httpd_global_handlers]
+;_google = {couch_httpd_proxy, handle_proxy_req, <<"http://www.google.com">>}
+
+[couch_httpd_auth]
+; If you set this to true, you should also uncomment the WWW-Authenticate line
+; above. If you don't configure a WWW-Authenticate header, CouchDB will send
+; Basic realm="server" in order to prevent you getting logged out.
+; require_valid_user = false
+
+[log]
+;level = debug
+
+[os_daemons]
+; For any commands listed here, CouchDB will attempt to ensure that
+; the process remains alive while CouchDB runs as well as shut them
+; down when CouchDB exits.
+;foo = /path/to/command -with args
+
+[daemons]
+; enable SSL support by uncommenting the following line and supply the PEM's below.
+; the default ssl port CouchDB listens on is 6984
+; httpsd = {couch_httpd, start_link, [https]}
+
+[ssl]
+;cert_file = /full/path/to/server_cert.pem
+;key_file = /full/path/to/server_key.pem
+;password = somepassword
+; set to true to validate peer certificates
+verify_ssl_certificates = false
+; Path to file containing PEM encoded CA certificates (trusted
+; certificates used for verifying a peer certificate). May be omitted if
+; you do not want to verify the peer.
+;cacert_file = /full/path/to/cacertf
+; The verification fun (optionnal) if not specidied, the default
+; verification fun will be used.
+;verify_fun = {Module, VerifyFun}
+ssl_certificate_max_depth = 1
+; To enable Virtual Hosts in CouchDB, add a vhost = path directive. All requests to
+; the Virual Host will be redirected to the path. In the example below all requests
+; to http://example.com/ are redirected to /database.
+; If you run CouchDB on a specific port, include the port number in the vhost:
+; example.com:5984 = /database
+
+[vhosts]
+;example.com = /database/
+
+[update_notification]
+;unique notifier name=/full/path/to/exe -with "cmd line arg"
+
+; To create an admin account uncomment the '[admins]' section below and add a
+; line in the format 'username = password'. When you next start CouchDB, it
+; will change the password to a hash (so that your passwords don't linger
+; around in plain-text files). You can add more admin accounts with more
+; 'username = password' lines. Don't forget to restart CouchDB after
+; changing this.
+[admins]
+;admin = mysecretpassword