File Coverage

blib/lib/CouchDB/Deploy.pm
Criterion Covered Total %
statement 27 47 57.4
branch 1 6 16.6
condition 1 10 10.0
subroutine 13 19 68.4
pod n/a
total 42 82 51.2


line stmt bran cond sub pod time code
1              
2             package CouchDB::Deploy;
3              
4 2     2   37037 use strict;
  2         6  
  2         95  
5 2     2   11 use warnings;
  2         3  
  2         92  
6              
7             our $VERSION = '0.03';
8              
9 2     2   982 use CouchDB::Client;
  2         98590  
  2         60  
10 2     2   660 use CouchDB::Deploy::Process;
  2         4  
  2         72  
11 2     2   10 use Carp qw(confess);
  2         4  
  2         250  
12 2         41 use Sub::Exporter -setup => {
13             exports => [
14             db => \&_build_db,
15             containing => \&_build_containing,
16             doc => \&_build_doc,
17             design => \&_build_design,
18             file => \&_build_file,
19             base64 => \&_build_base64,
20             ],
21             groups => {
22             default => [qw(db containing doc design file base64)],
23             },
24 2     2   2137 };
  2         29462  
25              
26             my $p;
27             BEGIN {
28 2   50 2   1126 my $server = $ARGV[0] || $ENV{COUCHDB_DEPLOY_SERVER} || 'http://localhost:5984/';
29 2 50       9 confess "No server provided." unless $server;
30 2         19 $p = CouchDB::Deploy::Process->new($server);
31             }
32              
33             sub _build_db {
34             return sub ($$) {
35 0     0   0 my ($db, $sub) = @_;
36 0         0 $p->createDBUnlessExists($db);
37 0         0 $sub->();
38 2     2   619 };
39             }
40              
41             sub _build_containing { # syntax sugar
42             return sub (&) {
43 0     0   0 my $sub = shift;
44 0         0 return $sub;
45 2     2   156 };
46             }
47              
48             sub _build_doc {
49             return sub (&) {
50 0     0   0 my $sub = shift;
51 0         0 my %data = $sub->();
52 0   0     0 my $id = delete($data{_id}) || confess "Document requires an '_id' field.";
53 0 0       0 confess "Document must not have a '_rev' field." if $data{_rev};
54 0   0     0 my $att = delete($data{_attachments}) || {};
55 0         0 $p->addDocumentUnlessExistsOrSame($id, \%data, $att);
56 2     2   61 };
57             }
58              
59             sub _build_design {
60             return sub (&) {
61 0     0   0 my $sub = shift;
62 0         0 my %data = $sub->();
63 0   0     0 my $id = delete($data{_id}) || confess "Design document requires an '_id' field.";
64 0 0       0 $id = "_design/$id" unless $id =~ m{^_design/};
65 0         0 $p->addDesignDocUnlessExistsOrSame($id, \%data);
66 2     2   47 };
67             }
68              
69             sub _build_file {
70             return sub ($) {
71 0     0   0 my $file = shift;
72 0         0 return $p->getFile($file);
73 2     2   46 };
74             }
75              
76             sub _build_base64 {
77             return sub ($) {
78 0     0   0 my $content = shift;
79 0         0 return CouchDB::Client::Doc->toBase64($content);
80 2     2   45 };
81             }
82              
83              
84             1;
85              
86             =pod
87              
88             =head1 NAME
89              
90             CouchDB::Deploy - Simple configuration scripting to deploy CouchDB databases
91              
92             =head1 SYNOPSIS
93              
94             use CouchDB::Deploy;
95              
96             db 'my-test-db/', containing {
97             doc {
98             _id => 'foo',
99             key => 'value',
100             _attachments => {
101             'foo.txt' => {
102             content_type => 'text/plain',
103             data => 'RGFodXRzIEZvciBXb3JsZCBEb21pbmF0aW9uXCE=',
104             },
105             'bar.svg' => {
106             content_type => 'image/svg+xml',
107             data => file 'dahut.svg',
108             },
109             'circle.html' => {
110             content_type => 'text/html;charset=utf-8',
111             data => base64 <
112            

Hello!

113             EOHTML
114             },
115             },
116             };
117             design {
118             _id => '_design/dahuts',
119             language => 'javascript',
120             views => {
121             'all' => {
122             map => "function(doc) { if (doc.type == 'dahut') emit(null, doc) }",
123             },
124             },
125             };
126             };
127            
128             # then run the above as
129            
130             my-db-config.pl http://my.server:5984/
131              
132             =head1 DESCRIPTION
133              
134             This module attempts to help with the common issue of deploying databases and updates to
135             database schemata in distributed development settings (which can simply be when you have
136             your own dev box and a server to deploy to).
137              
138             CouchDB does not have schemata, but it does have views (in design documents) on which
139             methods in your code are likely to rely. At times, you may also wish to have a given
140             document in a database, say the default configuration.
141              
142             What this module does is:
143              
144             =over
145              
146             =item *
147              
148             Check that a given database exists, and create it if not
149              
150             =item *
151              
152             Check that a given document exists and has the same content as the one provided, and
153             create or update it if not
154              
155             =item *
156              
157             Check that a given design document exists and has the same content as the one provided, and
158             create or update it if not
159              
160             =item *
161              
162             Provide a simple helper for attachments and the specific base64 that CouchDB requires.
163              
164             =back
165              
166             Currently this is done in Perl, using simple syntax sugar but it is expected that it will
167             be updated to also support a Config::Any approach.
168              
169             =head1 SYNTAX SUGAR
170              
171             =over 8
172              
173             =item db $DATABASE, containing { CONTENT }
174              
175             Creates a database with the given name, and adds the content, unless it exists. Keep in mind
176             that CouchDB databases must have a trailing slash in their names.
177              
178             =item doc { CONTENT }
179              
180             Creates a document with that content, unless it is there and up to date. Note that currently
181             only documents with an _id field are supported (otherwise we couldn't do the create-unless-exists
182             logic). The content is of the exact same structure as the JSON one would post to CouchDB.
183              
184             =item file $PATH
185              
186             Reads the file at $PATH, converts it to base64, and returns that on a single line. This is a
187             helper made to assist in creating CouchDB attachments. Note that in the current state it will
188             read the file into memory.
189              
190             =item base64 $CONTENT
191              
192             Returns the content encoded in single-line Base 64.
193              
194             =item design { CONTENT }
195              
196             Creates a design document with those views and parameters, unless it is there and up to date.
197             The content is of the exact same structure as the JSON one would post to CouchDB, except that
198             if the C<_id> field does not start with C<_design/> it will be automatically added.
199              
200             =back
201              
202             =head1 AUTHOR
203              
204             Robin Berjon,
205              
206             =head1 BUGS
207              
208             Please report any bugs or feature requests to bug-couchdb-deploy at rt.cpan.org, or through the
209             web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=CouchDb-Deploy.
210              
211             =head1 COPYRIGHT & LICENSE
212              
213             Copyright 2008 Robin Berjon, all rights reserved.
214              
215             This library is free software; you can redistribute it and/or modify it under the same terms as
216             Perl itself, either Perl version 5.8.8 or, at your option, any later version of Perl 5 you may
217             have available.
218              
219             =cut