Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Added new_from_env constructor.

Also Refactored auth logic into a role and converted from Any::Moose to
Moo.
  • Loading branch information...
commit d93f1af1aa2561e31373c20c9a2db7e756460ea3 1 parent 4f0c966
Naveed Massjouni authored
5 Changes
... ... @@ -1,5 +1,10 @@
1 1 Revision history for Net-OpenStack-Compute
2 2
  3 +1.1000 2012-04-12
  4 + Added new_from_env constructor.
  5 + Refactored auth logic into a role.
  6 + Converted to Moo from Any::Moose.
  7 +
3 8 1.0900 2012-04-05
4 9 Added support for OSCOMPUTE_INSECURE option.
5 10
22 bin/oscompute
@@ -23,27 +23,11 @@ sub setup {
23 23 $c->register(s => \&server, 'alias for server');
24 24 $c->register(i => \&image, 'alias for image');
25 25 $c->register(f => \&flavor, 'alias for flavor');
26   - $c->more_help(_parse_pod());
27   -
28   - my $msg = "%s env var is missing. Did you forget to source novarc?\n";
29   - die sprintf($msg, 'NOVA_URL or OS_AUTH_URL')
30   - unless $ENV{NOVA_URL} || $ENV{OS_AUTH_URL};
31   - die sprintf($msg, 'NOVA_USERNAME or OS_USERNAME')
32   - unless $ENV{NOVA_USERNAME} || $ENV{OS_USERNAME};
33   - die sprintf($msg, 'NOVA_PASSWORD or NOVA_API_KEY or OS_PASSWORD')
34   - unless $ENV{NOVA_PASSWORD} || $ENV{NOVA_API_KEY} || $ENV{OS_PASSWORD};
35 26
  27 + $c->more_help(_parse_pod());
36 28 $c->getopt('verbose|v', 'insecure', 'query|q=s');
37   - $c->stash->{compute} = Net::OpenStack::Compute->new(
38   - auth_url => $ENV{NOVA_URL} || $ENV{OS_AUTH_URL},
39   - user => $ENV{NOVA_USERNAME} || $ENV{OS_USERNAME},
40   - password => $ENV{NOVA_PASSWORD} || $ENV{NOVA_API_KEY}
41   - || $ENV{OS_PASSWORD},
42   - project_id => $ENV{NOVA_PROJECT_ID} || $ENV{OS_TENANT_NAME},
43   - region => $ENV{NOVA_REGION_NAME} || $ENV{OS_AUTH_REGION},
44   - service_name => $ENV{NOVA_SERVICE_NAME},
45   - is_rax_auth => $ENV{NOVA_RAX_AUTH},
46   - verify_ssl => !($c->options->{insecure} || $ENV{OSCOMPUTE_INSECURE}),
  29 + $c->stash->{compute} = Net::OpenStack::Compute->new_from_env(
  30 + $c->options->{insecure} ? (verify_ssl => 0) : ()
47 31 );
48 32 }
49 33
4 dist.ini
@@ -4,15 +4,15 @@ license = Perl_5
4 4 copyright_holder = Naveed Massjouni
5 5 copyright_year = 2011
6 6
7   -version = 1.0900
  7 +version = 1.1000
8 8
9 9 [Prereqs]
10   -Any::Moose = 0
11 10 App::Rad = 0
12 11 App::Rad::Plugin::MoreHelp = 0
13 12 HTTP::Request = 0
14 13 JSON = 0
15 14 LWP = 0
  15 +Moo = 0.009014
16 16 Pod::Select = 0
17 17
18 18 [MetaResources]
87 lib/Net/OpenStack/Compute.pm
... ... @@ -1,6 +1,5 @@
1 1 package Net::OpenStack::Compute;
2   -use Any::Moose;
3   -with 'Net::OpenStack::Compute::AuthRole';
  2 +use Moo;
4 3
5 4 # VERSION
6 5
@@ -8,34 +7,79 @@ use Carp;
8 7 use HTTP::Request;
9 8 use JSON qw(from_json to_json);
10 9 use LWP;
11   -use Net::OpenStack::Compute::Auth;
12   -
13   -has _auth => (
14   - is => 'rw',
15   - isa => 'Net::OpenStack::Compute::Auth',
16   - lazy => 1,
17   - default => sub {
18   - my $self = shift;
19   - return Net::OpenStack::Compute::Auth->new(
20   - map { $_, $self->$_ } qw(auth_url user password project_id region
21   - service_name is_rax_auth verify_ssl)
22   - );
23   - },
24   - handles => [qw(base_url token)],
  10 +#use Net::OpenStack::Compute::Auth;
  11 +
  12 +has auth_url => (is => 'rw', required => 1);
  13 +has user => (is => 'ro', required => 1);
  14 +has password => (is => 'ro', required => 1);
  15 +has project_id => (is => 'ro');
  16 +has region => (is => 'ro');
  17 +has service_name => (is => 'ro');
  18 +has is_rax_auth => (is => 'ro');
  19 +has verify_ssl => (is => 'ro', default => ! $ENV{OSCOMPUTE_INSECURE});
  20 +
  21 +has base_url => (
  22 + is => 'ro',
  23 + lazy => 1,
  24 + default => sub { shift->_auth_info->{base_url} },
  25 +);
  26 +has token => (
  27 + is => 'ro',
  28 + lazy => 1,
  29 + default => sub { shift->_auth_info->{token} },
25 30 );
  31 +has _auth_info => (is => 'ro', lazy => 1, builder => '_build_auth_info');
26 32
27   -has _ua => (
  33 +has _agent => (
28 34 is => 'ro',
29 35 lazy => 1,
30 36 default => sub {
31 37 my $self = shift;
32 38 my $agent = LWP::UserAgent->new(
33 39 ssl_opts => { verify_hostname => $self->verify_ssl });
34   - $agent->default_header(x_auth_token => $self->token);
35 40 return $agent;
36 41 },
37 42 );
38 43
  44 +with 'Net::OpenStack::Compute::AuthRole';
  45 +
  46 +sub new_from_env {
  47 + my ($self, %params) = @_;
  48 + my $msg = "%s env var is required. Did you forget to source novarc?\n";
  49 + die sprintf($msg, 'NOVA_URL or OS_AUTH_URL')
  50 + unless $ENV{NOVA_URL} || $ENV{OS_AUTH_URL};
  51 + die sprintf($msg, 'NOVA_USERNAME or OS_USERNAME')
  52 + unless $ENV{NOVA_USERNAME} || $ENV{OS_USERNAME};
  53 + die sprintf($msg, 'NOVA_PASSWORD or NOVA_API_KEY or OS_PASSWORD')
  54 + unless $ENV{NOVA_PASSWORD} || $ENV{NOVA_API_KEY} || $ENV{OS_PASSWORD};
  55 + my %env = (
  56 + auth_url => $ENV{NOVA_URL} || $ENV{OS_AUTH_URL},
  57 + user => $ENV{NOVA_USERNAME} || $ENV{OS_USERNAME},
  58 + password => $ENV{NOVA_PASSWORD} || $ENV{NOVA_API_KEY}
  59 + || $ENV{OS_PASSWORD},
  60 + project_id => $ENV{NOVA_PROJECT_ID} || $ENV{OS_TENANT_NAME},
  61 + region => $ENV{NOVA_REGION_NAME} || $ENV{OS_AUTH_REGION},
  62 + service_name => $ENV{NOVA_SERVICE_NAME},
  63 + is_rax_auth => $ENV{NOVA_RAX_AUTH},
  64 + );
  65 + return Net::OpenStack::Compute->new(%env, %params);
  66 +}
  67 +
  68 +sub BUILD {
  69 + my ($self) = @_;
  70 + # Make sure trailing slashes are removed from auth_url
  71 + my $auth_url = $self->auth_url;
  72 + $auth_url =~ s|/+$||;
  73 + $self->auth_url($auth_url);
  74 +}
  75 +
  76 +sub _build_auth_info {
  77 + my ($self) = @_;
  78 + my $auth_info = $self->get_auth_info();
  79 + $self->_agent->default_header(x_auth_token => $auth_info->{token});
  80 + return $auth_info;
  81 +}
  82 +
39 83 sub _get_query {
40 84 my %params = @_;
41 85 my $q = $params{query} or return '';
@@ -170,12 +214,12 @@ sub _url {
170 214
171 215 sub _get {
172 216 my ($self, $url) = @_;
173   - return $self->_ua->get($url);
  217 + return $self->_agent->get($url);
174 218 }
175 219
176 220 sub _post {
177 221 my ($self, $url, $data) = @_;
178   - return $self->_ua->post(
  222 + return $self->_agent->post(
179 223 $self->_url($url),
180 224 content_type => 'application/json',
181 225 content => to_json($data),
@@ -184,9 +228,8 @@ sub _post {
184 228
185 229 sub _delete {
186 230 my ($self, $url) = @_;
187   - print "_delete $url\n";
188 231 my $req = HTTP::Request->new(DELETE => $url);
189   - return $self->_ua->request($req);
  232 + return $self->_agent->request($req);
190 233 }
191 234
192 235 sub _action {
145 lib/Net/OpenStack/Compute/Auth.pm
... ... @@ -1,145 +0,0 @@
1   -package Net::OpenStack::Compute::Auth;
2   -use Any::Moose;
3   -with 'Net::OpenStack::Compute::AuthRole';
4   -
5   -#use Data::Dumper;
6   -use JSON qw(from_json to_json);
7   -use LWP;
8   -
9   -has _info => (is => 'ro', lazy => 1, builder => '_build_info');
10   -
11   -has base_url => (
12   - is => 'ro',
13   - lazy => 1,
14   - default => sub { shift->_info->{base_url} },
15   -);
16   -
17   -has token => (
18   - is => 'ro',
19   - lazy => 1,
20   - default => sub { shift->_info->{token} },
21   -);
22   -
23   -sub BUILD {
24   - my ($self) = @_;
25   - # Make sure trailing slash is removed from auth_url
26   - my $auth_url = $self->auth_url;
27   - $auth_url =~ s/\/$//;
28   - $self->auth_url($auth_url);
29   -}
30   -
31   -sub _build_info {
32   - my ($self) = @_;
33   - my $auth_url = $self->auth_url;
34   - my ($version) = $auth_url =~ /(v\d\.\d)$/;
35   - die "Could not determine version from url [$auth_url]" unless $version;
36   - return $self->auth_rax() if $self->is_rax_auth;
37   - return $self->auth_basic() if $version lt 'v2';
38   - return $self->auth_keystone();
39   -}
40   -
41   -has _ua => (
42   - is => 'ro',
43   - lazy => 1,
44   - default => sub {
45   - my $self = shift;
46   - my $agent = LWP::UserAgent->new(
47   - ssl_opts => { verify_hostname => $self->verify_ssl });
48   - return $agent;
49   - },
50   -);
51   -
52   -sub auth_basic {
53   - my ($self) = @_;
54   - my $res = $self->_ua->get($self->auth_url,
55   - x_auth_user => $self->user,
56   - x_auth_key => $self->password,
57   - x_auth_project_id => $self->project_id,
58   - );
59   - die $res->status_line . "\n" . $res->content unless $res->is_success;
60   -
61   - return {
62   - base_url => $res->header('x-server-management-url'),
63   - token => $res->header('x-auth-token'),
64   - };
65   -}
66   -
67   -sub auth_keystone {
68   - my ($self) = @_;
69   - return $self->_parse_catalog({
70   - auth => {
71   - tenantName => $self->project_id,
72   - passwordCredentials => {
73   - username => $self->user,
74   - password => $self->password,
75   - }
76   - }
77   - });
78   -}
79   -
80   -sub auth_rax {
81   - my ($self) = @_;
82   - return $self->_parse_catalog({
83   - auth => {
84   - 'RAX-KSKEY:apiKeyCredentials' => {
85   - apiKey => $self->password,
86   - username => $self->user,
87   - }
88   - }
89   - });
90   -}
91   -
92   -sub _parse_catalog {
93   - my ($self, $auth_data) = @_;
94   - my $res = $self->_ua->post($self->auth_url . "/tokens",
95   - content_type => 'application/json', content => to_json($auth_data));
96   - die $res->status_line . "\n" . $res->content unless $res->is_success;
97   - my $data = from_json($res->content);
98   - my $token = $data->{access}{token}{id};
99   -
100   - my @catalog = @{ $data->{access}{serviceCatalog} };
101   - @catalog = grep { $_->{type} eq 'compute' } @catalog;
102   - die "No compute catalog found" unless @catalog;
103   - if ($self->service_name) {
104   - @catalog = grep { $_->{name} eq $self->service_name } @catalog;
105   - die "No catalog found named " . $self->service_name unless @catalog;
106   - }
107   - my $catalog = $catalog[0];
108   - my $base_url = $catalog->{endpoints}[0]{publicURL};
109   - if ($self->region) {
110   - for my $endpoint (@{ $catalog->{endpoints} }) {
111   - my $region = $endpoint->{region} or next;
112   - if ($region eq $self->region) {
113   - $base_url = $endpoint->{publicURL};
114   - last;
115   - }
116   - }
117   - }
118   -
119   - return { base_url => $base_url, token => $token };
120   -}
121   -
122   -=head1 SYNOPSIS
123   -
124   - use Net::OpenStack::Compute::Auth;
125   -
126   - my $auth = Net::OpenStack::Compute::Auth->new(
127   - auth_url => $auth_url,
128   - user => $user,
129   - password => $key,
130   - project_id => $project_id,
131   - region => $region, # Optional
132   - );
133   -
134   - my $token = $auth->token;
135   - my $base_url = $auth->base_url;
136   -
137   -=head1 DESCRIPTION
138   -
139   -This class is responsible for authenticating for OpenStack.
140   -It supports the old style auth and the new
141   -L<Keystone|https://github.com/openstack/keystone> auth.
142   -
143   -=cut
144   -
145   -1;
114 lib/Net/OpenStack/Compute/AuthRole.pm
... ... @@ -1,13 +1,107 @@
1 1 package Net::OpenStack::Compute::AuthRole;
2   -use Any::Moose 'Role';
3   -
4   -has auth_url => (is => 'rw', required => 1);
5   -has user => (is => 'ro', required => 1);
6   -has password => (is => 'ro', required => 1);
7   -has project_id => (is => 'ro');
8   -has region => (is => 'ro');
9   -has service_name => (is => 'ro');
10   -has is_rax_auth => (is => 'ro', isa => 'Bool'); # Rackspace auth
11   -has verify_ssl => (is => 'ro', isa => 'Bool', default => 1);
  2 +use Moo::Role;
  3 +
  4 +use JSON qw(from_json to_json);
  5 +
  6 +requires qw(
  7 + auth_url
  8 + user
  9 + password
  10 + project_id
  11 + region
  12 + service_name
  13 + is_rax_auth
  14 + verify_ssl
  15 + _agent
  16 +);
  17 +
  18 +sub get_auth_info {
  19 + my ($self) = @_;
  20 + my $auth_url = $self->auth_url;
  21 + my ($version) = $auth_url =~ /(v\d\.\d)$/;
  22 + die "Could not determine version from url [$auth_url]" unless $version;
  23 + return $self->auth_rax() if $self->is_rax_auth;
  24 + return $self->auth_basic() if $version lt 'v2';
  25 + return $self->auth_keystone();
  26 +}
  27 +
  28 +sub auth_basic {
  29 + my ($self) = @_;
  30 + my $res = $self->_agent->get($self->auth_url,
  31 + x_auth_user => $self->user,
  32 + x_auth_key => $self->password,
  33 + x_auth_project_id => $self->project_id,
  34 + );
  35 + die $res->status_line . "\n" . $res->content unless $res->is_success;
  36 +
  37 + return {
  38 + base_url => $res->header('x-server-management-url'),
  39 + token => $res->header('x-auth-token'),
  40 + };
  41 +}
  42 +
  43 +sub auth_keystone {
  44 + my ($self) = @_;
  45 + return $self->_parse_catalog({
  46 + auth => {
  47 + tenantName => $self->project_id,
  48 + passwordCredentials => {
  49 + username => $self->user,
  50 + password => $self->password,
  51 + }
  52 + }
  53 + });
  54 +}
  55 +
  56 +sub auth_rax {
  57 + my ($self) = @_;
  58 + return $self->_parse_catalog({
  59 + auth => {
  60 + 'RAX-KSKEY:apiKeyCredentials' => {
  61 + apiKey => $self->password,
  62 + username => $self->user,
  63 + }
  64 + }
  65 + });
  66 +}
  67 +
  68 +sub _parse_catalog {
  69 + my ($self, $auth_data) = @_;
  70 + my $res = $self->_agent->post($self->auth_url . "/tokens",
  71 + content_type => 'application/json', content => to_json($auth_data));
  72 + die $res->status_line . "\n" . $res->content unless $res->is_success;
  73 + my $data = from_json($res->content);
  74 + my $token = $data->{access}{token}{id};
  75 +
  76 + my @catalog = @{ $data->{access}{serviceCatalog} };
  77 + @catalog = grep { $_->{type} eq 'compute' } @catalog;
  78 + die "No compute catalog found" unless @catalog;
  79 + if ($self->service_name) {
  80 + @catalog = grep { $_->{name} eq $self->service_name } @catalog;
  81 + die "No catalog found named " . $self->service_name unless @catalog;
  82 + }
  83 + my $catalog = $catalog[0];
  84 + my $base_url = $catalog->{endpoints}[0]{publicURL};
  85 + if ($self->region) {
  86 + for my $endpoint (@{ $catalog->{endpoints} }) {
  87 + my $region = $endpoint->{region} or next;
  88 + if ($region eq $self->region) {
  89 + $base_url = $endpoint->{publicURL};
  90 + last;
  91 + }
  92 + }
  93 + }
  94 +
  95 + return { base_url => $base_url, token => $token };
  96 +}
  97 +
  98 +=head1 DESCRIPTION
  99 +
  100 +This role is used by L<Net::OpenStack::Compute> for OpenStack authentication.
  101 +It supports the old 1.0 style auth,
  102 +L<Keystone|https://github.com/openstack/keystone> auth,
  103 +and Rackspace's RAX auth.
  104 +
  105 +=cut
12 106
13 107 1;

0 comments on commit d93f1af

Please sign in to comment.
Something went wrong with that request. Please try again.