| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package Etcd; | 
| 2 |  |  |  |  |  |  | $Etcd::VERSION = '0.003'; | 
| 3 |  |  |  |  |  |  | # ABSTRACT: Client library for etcd | 
| 4 |  |  |  |  |  |  |  | 
| 5 | 4 |  |  | 4 |  | 52631 | use namespace::sweep; | 
|  | 4 |  |  |  |  | 92688 |  | 
|  | 4 |  |  |  |  | 24 |  | 
| 6 |  |  |  |  |  |  |  | 
| 7 | 4 |  |  | 4 |  | 3054 | use HTTP::Tiny 0.014; | 
|  | 4 |  |  |  |  | 149530 |  | 
|  | 4 |  |  |  |  | 151 |  | 
| 8 | 4 |  |  | 4 |  | 1861 | use URI::Escape qw(uri_escape); | 
|  | 4 |  |  |  |  | 3807 |  | 
|  | 4 |  |  |  |  | 215 |  | 
| 9 | 4 |  |  | 4 |  | 20 | use Carp qw(croak); | 
|  | 4 |  |  |  |  | 4 |  | 
|  | 4 |  |  |  |  | 138 |  | 
| 10 |  |  |  |  |  |  |  | 
| 11 | 4 |  |  | 4 |  | 3167 | use Moo; | 
|  | 4 |  |  |  |  | 32416 |  | 
|  | 4 |  |  |  |  | 19 |  | 
| 12 | 4 |  |  | 4 |  | 6819 | use Type::Utils qw(class_type); | 
|  | 4 |  |  |  |  | 94010 |  | 
|  | 4 |  |  |  |  | 43 |  | 
| 13 | 4 |  |  | 4 |  | 3861 | use Types::Standard qw(Str Int Bool HashRef); | 
|  | 4 |  |  |  |  | 129639 |  | 
|  | 4 |  |  |  |  | 55 |  | 
| 14 |  |  |  |  |  |  |  | 
| 15 |  |  |  |  |  |  | has host => ( is => 'ro', isa => Str, default => '127.0.0.1' ); | 
| 16 |  |  |  |  |  |  | has port => ( is => 'ro', isa => Int, default => 4001 ); | 
| 17 |  |  |  |  |  |  |  | 
| 18 |  |  |  |  |  |  | has ssl => ( is => 'ro', isa => Bool, default => 0 ); | 
| 19 |  |  |  |  |  |  |  | 
| 20 |  |  |  |  |  |  | has http => ( is => 'lazy', isa => class_type('HTTP::Tiny') ); | 
| 21 | 6 |  |  | 6 |  | 1542 | sub _build_http { HTTP::Tiny->new }; | 
| 22 |  |  |  |  |  |  |  | 
| 23 |  |  |  |  |  |  | has version_prefix => ( is => 'ro', isa => Str, default => '/v2' ); | 
| 24 |  |  |  |  |  |  |  | 
| 25 |  |  |  |  |  |  | has _url_base => ( is => 'lazy' ); | 
| 26 |  |  |  |  |  |  | sub _build__url_base { | 
| 27 | 6 |  |  | 6 |  | 1048 | my ($self) = @_; | 
| 28 | 6 | 50 |  |  |  | 68 | ($self->ssl ? 'https' : 'http') .'://'.$self->host.':'.$self->port; | 
| 29 |  |  |  |  |  |  | } | 
| 30 |  |  |  |  |  |  |  | 
| 31 |  |  |  |  |  |  | sub _prep_url { | 
| 32 | 6 |  |  | 6 |  | 713 | my ($self, $path, %args) = @_; | 
| 33 | 6 |  |  |  |  | 17 | my $trailing = $path =~ m{/$}; | 
| 34 | 6 |  |  |  |  | 62 | my $url = $self->_url_base.join('/', map { uri_escape($_) } split('/', $path)); | 
|  | 22 |  |  |  |  | 187 |  | 
| 35 | 6 | 50 |  |  |  | 56 | $url .= '/' if $trailing; | 
| 36 | 6 | 100 |  |  |  | 57 | $url .= '?'.$self->http->www_form_urlencode(\%args) if %args; | 
| 37 | 6 |  |  |  |  | 146 | $url; | 
| 38 |  |  |  |  |  |  | } | 
| 39 |  |  |  |  |  |  |  | 
| 40 |  |  |  |  |  |  | sub api_exec { | 
| 41 | 6 |  |  | 6 | 0 | 101 | my ($self, $path, $method, %args) = @_; | 
| 42 | 6 |  |  |  |  | 61 | my $res = $self->http->request($method, $self->_prep_url($path, %args)); | 
| 43 | 6 | 100 | 66 |  |  | 107 | $res = $self->http->request($method, $res->{headers}->{location}) | 
| 44 |  |  |  |  |  |  | if $res && $res->{status} eq 307; | 
| 45 | 6 | 50 |  |  |  | 55 | return $res if $res->{success}; | 
| 46 | 0 | 0 |  |  |  | 0 | croak "$res->{status} $res->{reason}: $res->{content}" if $res->{status} >= 500; | 
| 47 | 0 |  |  |  |  | 0 | require Etcd::Error; | 
| 48 | 0 |  |  |  |  | 0 | die Etcd::Error->new_from_http($res); | 
| 49 |  |  |  |  |  |  | } | 
| 50 |  |  |  |  |  |  |  | 
| 51 |  |  |  |  |  |  | sub server_version { | 
| 52 | 1 |  |  | 1 | 1 | 4169 | my ($self) = @_; | 
| 53 | 1 |  |  |  |  | 5 | my $res = $self->api_exec('/version', 'GET'); | 
| 54 | 1 |  |  |  |  | 5 | $res->{content}; | 
| 55 |  |  |  |  |  |  | } | 
| 56 |  |  |  |  |  |  |  | 
| 57 |  |  |  |  |  |  | with 'Etcd::Keys'; | 
| 58 |  |  |  |  |  |  | with 'Etcd::Stats'; | 
| 59 |  |  |  |  |  |  |  | 
| 60 |  |  |  |  |  |  | 1; | 
| 61 |  |  |  |  |  |  |  | 
| 62 |  |  |  |  |  |  | __END__ |