Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: dagolden/pantry
base: 674566f701
...
head fork: dagolden/pantry
compare: a4bb9f2e90
Checking mergeability… Don't worry, you can still create the pull request.
  • 15 commits
  • 26 files changed
  • 0 commit comments
  • 1 contributor
View
13 lib/Pantry/App/Command/apply.pm
@@ -25,7 +25,7 @@ sub options {
}
sub valid_types {
- return qw/node role/
+ return qw/node role environment/
}
sub _apply_node {
@@ -38,6 +38,11 @@ sub _apply_role {
$self->_apply_obj($opt, 'role', $name);
}
+sub _apply_environment {
+ my ($self, $opt, $name) = @_;
+ $self->_apply_obj($opt, 'environment', $name);
+}
+
my %setters = (
node => {
default => 'set_attribute',
@@ -47,6 +52,10 @@ my %setters = (
default => 'set_default_attribute',
override => 'set_override_attribute',
},
+ environment => {
+ default => 'set_default_attribute',
+ override => 'set_override_attribute',
+ },
);
sub _apply_obj {
@@ -56,7 +65,7 @@ sub _apply_obj {
$options->{env} = $opt->{env} if $opt->{env};
my $obj = $self->_check_name($type, $name, $options);
- $self->_apply_runlist($obj, $opt);
+ $self->_apply_runlist($obj, $opt) unless $type eq 'environment';
for my $k ( sort keys %{$setters{$type}} ) {
if ( my $method = $setters{$type}{$k} ) {
View
16 lib/Pantry/App/Command/create.pm
@@ -24,7 +24,7 @@ sub options {
}
sub valid_types {
- return qw/node role cookbook/
+ return qw/node role environment cookbook/
}
sub _create_node {
@@ -61,6 +61,20 @@ sub _create_role {
return;
}
+sub _create_environment {
+ my ($self, $opt, $name) = @_;
+
+ my $environment = $self->pantry->environment( $name );
+ if ( -e $environment->path ) {
+ $self->usage_error( "Environment '$name' already exists" );
+ }
+ else {
+ $environment->save;
+ }
+
+ return;
+}
+
sub _create_cookbook {
my ($self, $opt, $name) = @_;
View
7 lib/Pantry/App/Command/delete.pm
@@ -19,7 +19,7 @@ sub command_type {
}
sub valid_types {
- return qw/node role/
+ return qw/node role environment/
}
sub options {
@@ -40,6 +40,11 @@ sub _delete_role {
$self->_delete_obj($opt, "role", $name);
}
+sub _delete_environment {
+ my ($self, $opt, $name) = @_;
+ $self->_delete_obj($opt, "environment", $name);
+}
+
sub _delete_obj {
my ($self, $opt, $type, $name) = @_;
View
7 lib/Pantry/App/Command/edit.pm
@@ -28,7 +28,7 @@ sub options {
}
sub valid_types {
- return qw/node role/
+ return qw/node role environment/
}
sub _edit_node {
@@ -41,6 +41,11 @@ sub _edit_role {
$self->_edit_obj($opt, 'role', $name);
}
+sub _edit_environment {
+ my ($self, $opt, $name) = @_;
+ $self->_edit_obj($opt, 'environment', $name);
+}
+
sub _edit_obj {
my ($self, $opt, $type, $name) = @_;
View
9 lib/Pantry/App/Command/list.pm
@@ -24,7 +24,7 @@ sub options {
}
sub valid_types {
- return qw/node nodes role roles/
+ return qw/node nodes role roles environment environments/
}
sub _list_nodes {
@@ -41,6 +41,13 @@ sub _list_roles {
*_list_role = *_list_roles; # alias
+sub _list_environments {
+ my ($self, $opt) = @_;
+ say $_ for $self->pantry->all_environments;
+}
+
+*_list_environment = *_list_environments; # alias
+
1;
=for Pod::Coverage options validate
View
7 lib/Pantry/App/Command/rename.pm
@@ -24,7 +24,7 @@ sub options{
}
sub valid_types {
- return qw/node role/
+ return qw/node role environment/
}
sub _rename_node {
@@ -37,6 +37,11 @@ sub _rename_role {
return $self->_rename_obj($opt, 'role', $name, $dest);
}
+sub _rename_environment {
+ my ($self, $opt, $name, $dest) = @_;
+ return $self->_rename_obj($opt, 'environment', $name, $dest);
+}
+
sub _rename_obj {
my ($self, $opt, $type, $name, $dest) = @_;
View
7 lib/Pantry/App/Command/show.pm
@@ -25,7 +25,7 @@ sub options {
}
sub valid_types {
- return qw/node role/
+ return qw/node role environment/
}
sub _show_node {
@@ -38,6 +38,11 @@ sub _show_role {
return $self->_show_obj($opt, 'role', $name);
}
+sub _show_environment {
+ my ($self, $opt, $name) = @_;
+ return $self->_show_obj($opt, 'environment', $name);
+}
+
sub _show_obj {
my ($self, $opt, $type, $name) = @_;
my $options;
View
11 lib/Pantry/App/Command/strip.pm
@@ -19,7 +19,7 @@ sub command_type {
}
sub valid_types {
- return qw/node role/
+ return qw/node role environment/
}
sub options {
@@ -37,6 +37,11 @@ sub _strip_role {
$self->_strip_obj($opt, 'role', $name);
}
+sub _strip_environment {
+ my ($self, $opt, $name) = @_;
+ $self->_strip_obj($opt, 'environment', $name);
+}
+
my %strippers = (
node => {
default => 'delete_attribute',
@@ -46,6 +51,10 @@ my %strippers = (
default => 'delete_default_attribute',
override => 'delete_override_attribute',
},
+ environment => {
+ default => 'delete_default_attribute',
+ override => 'delete_override_attribute',
+ },
);
sub _strip_obj {
View
29 lib/Pantry/Model/EnvRunList.pm
@@ -0,0 +1,29 @@
+use v5.14;
+use strict;
+use warnings;
+
+package Pantry::Model::EnvRunList;
+# ABSTRACT: Standalone runlist object for environment runlists
+# VERSION
+
+use Moose 2;
+use namespace::autoclean;
+
+with 'Pantry::Role::Runlist';
+
+1;
+
+=for Pod::Coverage method_names_here
+
+=head1 SYNOPSIS
+
+ use Pantry::Model::EnvRunList;
+
+=head1 DESCRIPTION
+
+Chef Roles can have environment-specific runlists. This is a standalone
+runlist object that merely instantiates the the Pantry::Role::Runlist role.
+
+=cut
+
+# vim: ts=2 sts=2 sw=2 et:
View
17 lib/Pantry/Model/Node.pm
@@ -29,6 +29,19 @@ has name => (
required => 1,
);
+=attr name
+
+This attribute is the name of the environment to which the node belongs. This defaults
+to C<_default>.
+
+=cut
+
+has env => (
+ is => 'ro',
+ isa => 'Str',
+ default => '_default',
+);
+
=attr run_list
This attribute is provided by the L<Pantry::Role::Runlist> role and holds a list
@@ -139,10 +152,11 @@ sub save {
return $self->save_as( $self->path );
}
-my @top_level_keys = qw/name run_list pantry_host pantry_port pantry_user/;
+my @top_level_keys = qw/name run_list pantry_host pantry_port pantry_user chef_environment/;
sub _freeze {
my ($self, $data) = @_;
+ $data->{chef_environment} = delete $data->{env};
my $attr = delete $data->{attributes};
for my $k ( keys %$attr ) {
next if grep { $k eq $_ } @top_level_keys;
@@ -164,6 +178,7 @@ sub _thaw {
}
}
$data->{attributes} = $attr;
+ $data->{env} = delete( $data->{chef_environment} ) || "_default";
return $data;
}
View
1  lib/Pantry/Model/Pantry.pm
@@ -106,6 +106,7 @@ Otherwise, it will be created in memory (but will not be persisted to disk).
sub node {
my ($self, $node_name, $options ) = @_;
$options //= {};
+ $options->{env} //= "_default";
$node_name = lc $node_name;
require Pantry::Model::Node;
my $path = $self->_node_path( $node_name, $options->{env} );
View
54 lib/Pantry/Model/Role.pm
@@ -7,7 +7,9 @@ package Pantry::Model::Role;
use Moose 2;
use MooseX::Types::Path::Class::MoreCoercions qw/File/;
+use Carp qw/croak/;
use List::AllUtils qw/uniq first/;
+use Pantry::Model::EnvRunList;
use Pantry::Model::Util qw/hash_to_dot dot_to_hash/;
use namespace::autoclean;
@@ -125,6 +127,49 @@ has override_attributes => (
},
);
+has env_run_lists => (
+ is => 'bare',
+ isa => 'HashRef[Pantry::Model::EnvRunList]',
+ traits => ['Hash'],
+ default => sub { +{} },
+ handles => {
+ set_env_run_list => 'set',
+ get_env_run_list => 'get',
+ delete_env_run_list => 'delete',
+ },
+);
+
+sub append_to_env_run_list {
+ my ($self, $env, $items) = @_;
+ croak "append_to_env_runlist requires an environment name"
+ unless $env;
+ croak "append_to_env_runlist requires an array reference of items to append"
+ unless ref($items) eq 'ARRAY';
+
+ my $runlist;
+ unless ( $runlist = $self->get_env_run_list($env) ) {
+ $runlist = Pantry::Model::EnvRunList->new;
+ $self->set_env_run_list( $env => $runlist );
+ }
+
+ $runlist->append_to_run_list( @$items );
+ return;
+}
+
+sub remove_from_env_run_list {
+ my ($self, $env, $items) = @_;
+ croak "remove_from_env_runlist requires an environment name"
+ unless $env;
+ croak "remove_from_env_runlist requires an array reference of items to append"
+ unless ref($items) eq 'ARRAY';
+
+ if ( my $runlist = $self->get_env_run_list($env) ) {
+ $runlist->remove_from_run_list( @$items );
+ }
+
+ return;
+}
+
=method save
Saves the node to a file in the pantry. If the private C<_path>
@@ -150,6 +195,10 @@ sub _freeze {
}
$data->{$attr} = $new;
}
+ for my $env ( keys %{$data->{env_run_lists}} ) {
+ my $obj = delete $data->{env_run_lists}{$env};
+ $data->{env_run_lists}{$env} = [ $obj->run_list ];
+ }
$data->{json_class} = "Chef::Role";
$data->{chef_type} = "role";
return $data;
@@ -171,6 +220,11 @@ sub _thaw {
}
$data->{$attr} = $new;
}
+ for my $env ( keys %{$data->{env_run_lists}} ) {
+ my $obj = Pantry::Model::EnvRunList->new;
+ $obj->append_to_run_list(@{delete $data->{env_run_lists}{$env}});
+ $data->{env_run_lists}{$env} = $obj;
+ }
return $data;
}
View
3  lib/Pantry/Role/Serializable.pm
@@ -12,6 +12,7 @@ use namespace::autoclean;
use File::Basename qw/dirname/;
use File::Path qw/mkpath/;
use File::Slurp qw/read_file write_file/;
+use Storable qw/dclone/;
use JSON 2;
parameter freezer => (
@@ -67,7 +68,7 @@ with leading underscores are considered "private" and are omitted.
delete $data->{$_} for grep { /^_/ } keys %$data; # delete private attributes
if ($freezer) {
- $data = $self->$freezer($data);
+ $data = $self->$freezer(dclone $data);
}
# XXX check if string needs UTF-8 encoding?
View
224 t/app/apply.t
@@ -5,6 +5,7 @@ no warnings 'qw'; # separating words with commas
use autodie;
use Test::More 0.92;
use Test::Deep 0.110 qw/cmp_deeply/;
+use Storable qw/dclone/;
use lib 't/lib';
use TestHelper;
@@ -12,180 +13,193 @@ use JSON;
my %templates = (
node => {
- run_list => [],
+ chef_environment => '_default',
+ run_list => [],
},
role => {
- json_class => "Chef::Role",
- chef_type => "role",
- run_list => [],
- default_attributes => {},
+ json_class => "Chef::Role",
+ chef_type => "role",
+ run_list => [],
+ env_run_lists => {},
+ default_attributes => {},
+ override_attributes => {},
+ },
+ environment => {
+ json_class => "Chef::Environment",
+ chef_type => "environment",
+ default_attributes => {},
override_attributes => {},
},
);
-my @node_subtests = (
+my @recipe_role_subtests = (
{
- argv => [ qw/-r nginx/ ],
+ argv => [qw/-r nginx/],
expected => {
- run_list => [ 'recipe[nginx]' ],
+ run_list => ['recipe[nginx]'],
},
},
{
- argv => [ qw/-R web/ ],
+ argv => [qw/-R web/],
expected => {
- run_list => [ 'role[web]' ],
+ run_list => ['role[web]'],
},
},
{
- argv => [ qw/-r postfix -r iptables -R web/ ],
+ argv => [qw/-r postfix -r iptables -R web/],
expected => {
- run_list => [ qw/role[web] recipe[postfix] recipe[iptables]/ ],
+ run_list => [qw/role[web] recipe[postfix] recipe[iptables]/],
},
},
+);
+
+my @flat_attribute_subtests = (
{
- argv => [ qw/-d nginx.port=80/ ],
+ argv => [qw/-d nginx.port=80/],
expected => {
run_list => [],
- nginx => { port => 80 },
+ nginx => { port => 80 },
},
},
{
- argv => [ qw/-d nginx.port=80,8080/ ],
+ argv => [qw/-d nginx.port=80,8080/],
expected => {
run_list => [],
- nginx => { port => [80,8080] },
+ nginx => { port => [ 80, 8080 ] },
},
},
{
- argv => [ qw/-d nginx\.port=80,8000\,8080/ ],
+ argv => [qw/-d nginx\.port=80,8000\,8080/],
expected => {
- run_list => [],
- 'nginx.port' => [80,'8000,8080'],
+ run_list => [],
+ 'nginx.port' => [ 80, '8000,8080' ],
},
},
{
- argv => [ qw/-d nginx\.enable=false/ ],
+ argv => [qw/-d nginx\.enable=false/],
expected => {
- run_list => [],
+ run_list => [],
'nginx.enable' => JSON::false,
},
},
{
- argv => [ qw/-d nginx\.enable=true/ ],
+ argv => [qw/-d nginx\.enable=true/],
expected => {
- run_list => [],
+ run_list => [],
'nginx.enable' => JSON::true,
},
},
);
+my @deep_attribute_subtests = (
+ {
+ argv => [qw/-d nginx.port=80/],
+ expected => {
+ default_attributes => {
+ nginx => { port => 80 },
+ },
+ },
+ },
+ {
+ argv => [qw/--override nginx.port=80/],
+ expected => {
+ override_attributes => {
+ nginx => { port => 80 },
+ },
+ },
+ },
+ {
+ argv => [qw/-d nginx.port=80,8080/],
+ expected => {
+ default_attributes => {
+ nginx => { port => [ 80, 8080 ] },
+ },
+ },
+ },
+ {
+ argv => [qw/-d nginx\.port=80,8000\,8080/],
+ expected => {
+ default_attributes => {
+ 'nginx.port' => [ 80, '8000,8080' ],
+ },
+ },
+ },
+ {
+ argv => [qw/-d nginx\.enable=false/],
+ expected => {
+ default_attributes => {
+ 'nginx.enable' => JSON::false,
+ }
+ },
+ },
+ {
+ argv => [qw/-d nginx\.enable=true/],
+ expected => {
+ default_attributes => {
+ 'nginx.enable' => JSON::true,
+ }
+ },
+ },
+);
+
my @cases = (
{
type => "node",
name => 'foo.example.com',
- new => sub { my ($p,$n) = @_; $p->node($n) },
- subtests => \@node_subtests,
+ new => sub { my ( $p, $n ) = @_; $p->node($n) },
+ subtests => [ @recipe_role_subtests, @flat_attribute_subtests ],
},
{
- type => "node",
- name => 'foo.example.com',
- new => sub { my ($p,$n) = @_; $p->node($n, {env => 'test'}) },
+ type => "node",
+ name => 'foo.example.com',
+ new => sub { my ( $p, $n ) = @_; $p->node( $n, { env => 'test' } ) },
env_args => [qw/-E test/],
- subtests => \@node_subtests,
+ subtests => [ @recipe_role_subtests, @flat_attribute_subtests ],
},
{
type => "role",
name => 'web',
- new => sub { my ($p,$n) = @_; $p->role($n) },
- subtests => [
- {
- argv => [ qw/-r nginx/ ],
- expected => {
- run_list => [ 'recipe[nginx]' ],
- },
- },
- {
- argv => [ qw/-R web/ ],
- expected => {
- run_list => [ 'role[web]' ],
- },
- },
- {
- argv => [ qw/-d nginx.port=80/ ],
- expected => {
- default_attributes => {
- nginx => { port => 80 },
- },
- },
- },
- {
- argv => [ qw/--override nginx.port=80/ ],
- expected => {
- override_attributes => {
- nginx => { port => 80 },
- },
- },
- },
- {
- argv => [ qw/-d nginx.port=80,8080/ ],
- expected => {
- default_attributes => {
- nginx => { port => [80,8080] },
- },
- },
- },
- {
- argv => [ qw/-d nginx\.port=80,8000\,8080/ ],
- expected => {
- default_attributes => {
- 'nginx.port' => [80,'8000,8080'],
- },
- },
- },
- {
- argv => [ qw/-d nginx\.enable=false/ ],
- expected => {
- default_attributes => {
- 'nginx.enable' => JSON::false,
- }
- },
- },
- {
- argv => [ qw/-d nginx\.enable=true/ ],
- expected => {
- default_attributes => {
- 'nginx.enable' => JSON::true,
- }
- },
- },
- ],
+ new => sub { my ( $p, $n ) = @_; $p->role($n) },
+ subtests => [ @recipe_role_subtests, @deep_attribute_subtests ],
+ },
+
+ {
+ type => "environment",
+ name => 'test',
+ new => sub { my ( $p, $n ) = @_; $p->environment($n) },
+ subtests => [ @deep_attribute_subtests ],
},
);
-for my $c ( @cases ) {
- for my $st ( @{$c->{subtests}} ) {
- my @argv = @{$st->{argv}};
- push @argv, @{$c->{env_args}} if exists $c->{env_args};
+for my $c (@cases) {
+ for my $st ( @{ $c->{subtests} } ) {
+ my @argv = @{ $st->{argv} };
+ push @argv, @{ $c->{env_args} } if exists $c->{env_args};
subtest "$c->{type} NAME @argv" => sub {
- my ($wd, $pantry) = _create_pantry();
- my $obj = $c->{new}->($pantry, $c->{name});
+ my ( $wd, $pantry ) = _create_pantry();
+ my $obj = $c->{new}->( $pantry, $c->{name} );
- _try_command('create', $c->{type}, $c->{name}, @{$c->{env_args} || []});
- _try_command('apply', $c->{type}, $c->{name}, @argv) ;
+ _try_command( 'create', $c->{type}, $c->{name}, @{ $c->{env_args} || [] } );
+ _try_command( 'apply', $c->{type}, $c->{name}, @argv );
- my $data = _thaw_file( $obj->path );
- $st->{expected}{name} //= $c->{name};
- for my $k ( keys %{$templates{$c->{type}}} ) {
- $st->{expected}{$k} //= $templates{$c->{type}}{$k};
+ my $data = _thaw_file( $obj->path );
+ my $expected = dclone $st->{expected};
+ $expected->{name} //= $c->{name};
+ for my $k ( keys %{ $templates{ $c->{type} } } ) {
+ $expected->{$k} //= $templates{ $c->{type} }{$k};
+ }
+ if ( $c->{env_args} ) {
+ $expected->{chef_environment} = $c->{env_args}[-1];
}
- cmp_deeply( $data, $st->{expected}, "data file correct" )
+ cmp_deeply( $data, $expected, "data file correct" )
or diag explain $data;
};
}
}
done_testing;
+
# COPYRIGHT
View
16 t/app/create.t
@@ -15,6 +15,7 @@ my @cases = (
name => 'foo.example.com',
new => sub { my ($p,$n) = @_; $p->node($n) },
empty => {
+ chef_environment => '_default',
run_list => [],
},
},
@@ -26,6 +27,7 @@ my @cases = (
new => sub { my ($p,$n) = @_; $p->node($n) },
empty => {
run_list => [],
+ chef_environment => '_default',
pantry_host => 'localhost',
pantry_port => 2222,
pantry_user => 'vagrant',
@@ -38,6 +40,7 @@ my @cases = (
opts => [qw/-E test/],
new => sub { my ($p,$n) = @_; $p->node($n, {env => 'test'}) },
empty => {
+ chef_environment => 'test',
run_list => [],
},
},
@@ -50,6 +53,19 @@ my @cases = (
json_class => "Chef::Role",
chef_type => "role",
run_list => [],
+ env_run_lists => {},
+ default_attributes => {},
+ override_attributes => {},
+ },
+ },
+ {
+ label => "environment",
+ type => "environment",
+ name => 'test',
+ new => sub { my ($p,$n) = @_; $p->environment($n) },
+ empty => {
+ json_class => "Chef::Environment",
+ chef_type => "environment",
default_attributes => {},
override_attributes => {},
},
View
6 t/app/delete.t
@@ -27,6 +27,12 @@ my @cases = (
name => 'web',
new => sub { my ($p,$n) = @_; $p->role($n) },
},
+ {
+ label => "environment",
+ type => "environment",
+ name => 'test',
+ new => sub { my ($p,$n) = @_; $p->environment($n) },
+ },
);
local $ENV{PERL_MM_USE_DEFAULT} = 1;
View
6 t/app/edit.t
@@ -25,6 +25,12 @@ my @cases = (
new => sub { my ($p,$n) = @_; $p->node($n, {env => 'test'}) },
},
{
+ label => "environment",
+ type => "environment",
+ name => 'test',
+ new => sub { my ($p,$n) = @_; $p->environment($n) },
+ },
+ {
label => "role",
type => "role",
name => 'web',
View
6 t/app/list.t
@@ -27,6 +27,12 @@ my @cases = (
names => ['web', 'db'],
new => sub { my ($p,$n) = @_; $p->role($n) },
},
+ {
+ label => "environments",
+ type => "environment",
+ names => ['test', 'prod'],
+ new => sub { my ($p,$n) = @_; $p->environment($n) },
+ },
);
for my $c ( @cases ) {
View
77 t/app/options.t
@@ -1,77 +0,0 @@
-use v5.14;
-use strict;
-use warnings;
-use autodie;
-use Test::More 0.96;
-
-use lib 't/privlib';
-use App::Cmd::Tester;
-use Pantry::App;
-use JSON;
-
-my @cases = (
- {
- cli => [qw(--recipe arecipe)],
- args => [],
- opts => { recipe => [ 'arecipe' ] },
- },
- {
- cli => [qw(-r arecipe)],
- args => [],
- opts => { recipe => [ 'arecipe' ] },
- },
- {
- cli => [qw(-r arecipe -r brecipe)],
- args => [],
- opts => { recipe => [ 'arecipe', 'brecipe' ] },
- },
- {
- cli => [qw(--default nginx.port=80)],
- args => [],
- opts => { default => [ 'nginx.port=80' ] },
- },
- {
- cli => [qw(-d nginx.port=80)],
- args => [],
- opts => { default => [ 'nginx.port=80' ] },
- },
- {
- cli => [qw(-d nginx.port)],
- args => [],
- opts => { default => [ 'nginx.port' ] },
- },
- {
- cli => [qw(-d nginx.port=80 -d nginx.user=nobody)],
- args => [],
- opts => { default => [ 'nginx.port=80', 'nginx.user=nobody' ] },
- },
-);
-
-for my $case ( @cases ) {
- my @cli = @{$case->{cli}};
- my $label = join(" ", @cli);
- my $exp = {
- args => $case->{args},
- opts => $case->{opts},
- };
-
- my $r = test_app( 'Pantry::App' => [ 'clidump', @cli ] );
-
- if ( $r->error ) {
- fail ( "Error: $label" ) or diag explain $r;
- }
- else {
- my $got = eval { decode_json( $r->stdout ) };
- if ( $got ) {
- is_deeply( $got, $exp , "Check: $label" )
- or diag join("\n", "GOT:", explain($got), "\nEXPECTED:", explain($exp) );
- }
- else {
- my $err = $@;
- fail "Error: $label" or diag $err;
- }
- }
-}
-
-done_testing;
-# COPYRIGHT
View
6 t/app/rename.t
@@ -27,6 +27,12 @@ my @cases = (
name => 'web',
new => sub { my ($p,$n) = @_; $p->role($n) },
},
+ {
+ label => "environment",
+ type => "environment",
+ name => 'test',
+ new => sub { my ($p,$n) = @_; $p->environment($n) },
+ },
);
local $ENV{PERL_MM_USE_DEFAULT} = 1;
View
26 t/app/show.t
@@ -14,8 +14,10 @@ my @cases = (
type => "node",
name => 'foo.example.com',
new => sub { my ($p,$n) = @_; $p->node($n) },
+ args => [qw/-r nginx -d nginx.port=80/],
expected => {
run_list => [ 'recipe[nginx]' ],
+ chef_environment => '_default',
nginx => {
port => 80
},
@@ -26,9 +28,10 @@ my @cases = (
type => "node",
name => 'foo.example.com',
new => sub { my ($p,$n) = @_; $p->node($n, {env => 'test'}) },
- args => [qw/--env test/],
+ args => [qw/-r nginx -d nginx.port=80 --env test/],
expected => {
run_list => [ 'recipe[nginx]' ],
+ chef_environment => 'test',
nginx => {
port => 80
},
@@ -39,10 +42,29 @@ my @cases = (
type => "role",
name => 'web',
new => sub { my ($p,$n) = @_; $p->role($n) },
+ args => [qw/-r nginx -d nginx.port=80/],
expected => {
json_class => "Chef::Role",
chef_type => "role",
run_list => [ 'recipe[nginx]' ],
+ env_run_lists => {},
+ default_attributes => {
+ nginx => {
+ port => 80
+ },
+ },
+ override_attributes => {},
+ },
+ },
+ {
+ label => "environment",
+ type => "environment",
+ name => 'web',
+ new => sub { my ($p,$n) = @_; $p->environment($n) },
+ args => [qw/-d nginx.port=80/],
+ expected => {
+ json_class => "Chef::Environment",
+ chef_type => "environment",
default_attributes => {
nginx => {
port => 80
@@ -61,7 +83,7 @@ for my $c ( @cases ) {
my $obj = $c->{new}->($pantry, $c->{name});
_try_command('create', $c->{type}, $c->{name}, @args);
- _try_command('apply', $c->{type}, $c->{name}, @args, qw(-r nginx -d nginx.port=80));
+ _try_command('apply', $c->{type}, $c->{name}, @args);
my $result = _try_command('show', $c->{type}, $c->{name}, @args);
my $data = eval { decode_json( $result->output ) };
View
217 t/app/strip.t
@@ -4,6 +4,8 @@ use warnings;
no warnings 'qw'; # separating words with commas
use autodie;
use Test::More 0.92;
+use Test::Deep 0.110 qw/cmp_deeply/;
+use Storable qw/dclone/;
use lib 't/lib';
use TestHelper;
@@ -11,18 +13,26 @@ use JSON;
my %templates = (
node => {
- run_list => [],
+ chef_environment => '_default',
+ run_list => [],
},
role => {
json_class => "Chef::Role",
chef_type => "role",
run_list => [],
+ env_run_lists => {},
+ default_attributes => {},
+ override_attributes => {},
+ },
+ environment => {
+ json_class => "Chef::Environment",
+ chef_type => "environment",
default_attributes => {},
override_attributes => {},
},
);
-my @node_subtests = (
+my @recipe_role_subtests = (
{
label => "strip recipe",
apply => [qw/-r nginx/],
@@ -59,6 +69,9 @@ my @node_subtests = (
run_list => [qw/recipe[postfix]/],
},
},
+);
+
+my @flat_attribute_subtests = (
{
label => "strip attribute",
apply => [qw/-d nginx.port=80/],
@@ -104,124 +117,128 @@ my @node_subtests = (
},
);
-my @cases = (
+my @deep_attribute_subtests = (
{
- type => "node",
- name => 'foo.example.com',
- new => sub { my ( $p, $n ) = @_; $p->node($n) },
- subtests => \@node_subtests,
+ label => "strip default attribute",
+ apply => [qw/-d nginx.port=80/],
+ strip => [qw/-d nginx.port/],
+ expected => {},
},
{
- type => "node",
- name => 'foo.example.com',
- new => sub { my ( $p, $n ) = @_; $p->node($n, {env => 'test'}) },
- env_args => [qw/-E test/],
- subtests => \@node_subtests,
- },
- {
- type => "role",
- name => 'web',
- new => sub { my ( $p, $n ) = @_; $p->role($n) },
- subtests => [
- {
- label => "strip recipe",
- apply => [qw/-r nginx/],
- strip => [qw/-r nginx/],
- expected => {},
- },
- {
- label => "strip only one recipe",
- apply => [qw/-r nginx -r postfix/],
- strip => [qw/-r nginx/],
- expected => {
- run_list => [qw/recipe[postfix]/],
- },
- },
- {
- label => "strip default attribute",
- apply => [qw/-d nginx.port=80/],
- strip => [qw/-d nginx.port/],
- expected => {},
- },
- {
- label => "strip override attribute",
- apply => [qw/--override nginx.port=80/],
- strip => [qw/--override nginx.port/],
- expected => {},
- },
- {
- label => "strip only one attribute",
- apply => [qw/-d nginx.port=80 -d nginx.user=nobody/],
- strip => [qw/-d nginx.user/],
- expected => {
- default_attributes => {
- nginx => { port => 80 },
- },
- },
+ label => "strip override attribute",
+ apply => [qw/--override nginx.port=80/],
+ strip => [qw/--override nginx.port/],
+ expected => {},
+ },
+ {
+ label => "strip only one attribute",
+ apply => [qw/-d nginx.port=80 -d nginx.user=nobody/],
+ strip => [qw/-d nginx.user/],
+ expected => {
+ default_attributes => {
+ nginx => { port => 80 },
},
- {
- label => "strip only one attribute default/override",
- apply => [qw/-d nginx.port=80 --override nginx.user=nobody/],
- strip => [qw/--override nginx.user/],
- expected => {
- default_attributes => {
- nginx => { port => 80 },
- },
- },
+ },
+ },
+ {
+ label => "strip only one attribute default/override",
+ apply => [qw/-d nginx.port=80 --override nginx.user=nobody/],
+ strip => [qw/--override nginx.user/],
+ expected => {
+ default_attributes => {
+ nginx => { port => 80 },
},
- {
- label => "strip entire attribute hash shoudn't work",
- apply => [qw/-d nginx.port=80 -d nginx.user=nobody/],
- strip => [qw/-d nginx/],
- expected => {
- default_attributes => {
- nginx => {
- port => 80,
- user => 'nobody',
- },
- },
+ },
+ },
+ {
+ label => "strip entire attribute hash shoudn't work",
+ apply => [qw/-d nginx.port=80 -d nginx.user=nobody/],
+ strip => [qw/-d nginx/],
+ expected => {
+ default_attributes => {
+ nginx => {
+ port => 80,
+ user => 'nobody',
},
},
- {
- label => "strip attribute with useless value",
- apply => [qw/-d nginx.port=80/],
- strip => [qw/-d nginx.port=8080/],
- expected => {},
- },
- {
- label => "strip attribute list",
- apply => [qw/-d nginx.port=80,8080/],
- strip => [qw/-d nginx.port/],
- expected => {},
- },
- {
- label => "strip escaped attribute",
- apply => [qw/-d nginx\.port=80/],
- strip => [qw/-d nginx\.port/],
- expected => {},
- },
- ],
+ },
+ },
+ {
+ label => "strip attribute with useless value",
+ apply => [qw/-d nginx.port=80/],
+ strip => [qw/-d nginx.port=8080/],
+ expected => {},
+ },
+ {
+ label => "strip attribute list",
+ apply => [qw/-d nginx.port=80,8080/],
+ strip => [qw/-d nginx.port/],
+ expected => {},
+ },
+ {
+ label => "strip escaped attribute",
+ apply => [qw/-d nginx\.port=80/],
+ strip => [qw/-d nginx\.port/],
+ expected => {},
+ },
+);
+
+my @cases = (
+ {
+ type => "node",
+ name => 'foo.example.com',
+ new => sub { my ( $p, $n ) = @_; $p->node($n) },
+ subtests => [ @recipe_role_subtests, @flat_attribute_subtests ],
+ },
+ {
+ type => "node",
+ name => 'foo.example.com',
+ new => sub { my ( $p, $n ) = @_; $p->node( $n, { env => 'test' } ) },
+ env_args => [qw/-E test/],
+ subtests => [ @recipe_role_subtests, @flat_attribute_subtests ],
+ },
+ {
+ type => "role",
+ name => 'web',
+ new => sub { my ( $p, $n ) = @_; $p->role($n) },
+ subtests => [ @recipe_role_subtests, @deep_attribute_subtests ],
+ },
+ {
+ type => "environment",
+ name => 'test',
+ new => sub { my ( $p, $n ) = @_; $p->environment($n) },
+ subtests => [@deep_attribute_subtests],
},
);
for my $c (@cases) {
for my $st ( @{ $c->{subtests} } ) {
- my $env = exists($c->{env_args}) ? " (@{$c->{env_args}})" : "";
+ my $env = exists( $c->{env_args} ) ? " (@{$c->{env_args}})" : "";
subtest "$c->{type} $st->{label}$env" => sub {
my ( $wd, $pantry ) = _create_pantry();
my $obj = $c->{new}->( $pantry, $c->{name} );
- _try_command( 'create', $c->{type}, $c->{name}, @{$c->{env_args} || []});
- _try_command( 'apply', $c->{type}, $c->{name}, @{ $st->{apply} }, @{$c->{env_args} || [] } );
- _try_command( 'strip', $c->{type}, $c->{name}, @{ $st->{strip} }, @{$c->{env_args} || [] } );
+ _try_command( 'create', $c->{type}, $c->{name}, @{ $c->{env_args} || [] } );
+ _try_command(
+ 'apply', $c->{type}, $c->{name}, @{ $st->{apply} },
+ @{ $c->{env_args} || [] }
+ );
+ _try_command(
+ 'strip', $c->{type}, $c->{name}, @{ $st->{strip} },
+ @{ $c->{env_args} || [] }
+ );
- my $data = _thaw_file( $obj->path );
- $st->{expected}{name} //= $c->{name};
+ my $data = _thaw_file( $obj->path );
+ my $expected = dclone $st->{expected};
+ $expected->{name} //= $c->{name};
for my $k ( keys %{ $templates{ $c->{type} } } ) {
- $st->{expected}{$k} //= $templates{ $c->{type} }{$k};
+ $expected->{$k} //= $templates{ $c->{type} }{$k};
+ }
+ if ( $c->{env_args} ) {
+ $expected->{chef_environment} = $c->{env_args}[-1];
}
- is_deeply( $data, $st->{expected}, "data file correct" )
+ cmp_deeply( $data, $expected, "data file correct" )
or diag explain $data;
};
}
View
3  t/model/node.t
@@ -97,6 +97,7 @@ subtest 'node attribute serialization' => sub {
my $data = _thaw_file("node.json");
is_deeply( $data, {
name => 'foo.example.com',
+ chef_environment => '_default',
run_list => [],
nginx => {
port => 80,
@@ -126,6 +127,7 @@ subtest 'node attribute escape dots' => sub {
my $data = _thaw_file("node.json");
is_deeply( $data, {
name => 'foo.example.com',
+ chef_environment => '_default',
run_list => [],
'nginx.port' => 80,
'deep' => {
@@ -159,6 +161,7 @@ subtest 'boolean values' => sub {
my $data = _thaw_file("node.json");
is_deeply( $data, {
name => 'foo.example.com',
+ chef_environment => '_default',
run_list => [],
'nginx.enabled' => JSON::true,
'nginx.logging' => JSON::false,
View
1  t/model/pantry.t
@@ -52,6 +52,7 @@ subtest "create/retrieve a node in an environement" => sub {
"saved a node to test environment directory"
);
ok( my $node2 = $pantry->node("foo.example.com", { env => "test"}), "retrieved a node from test environement");
+ is( $node2->env, 'test', "node.chef_environment correct" );
ok( $node2->save, "saved it again" );
};
View
35 t/model/role.t
@@ -92,6 +92,7 @@ subtest 'role attribute serialization' => sub {
json_class => 'Chef::Role',
chef_type => 'role',
run_list => [],
+ env_run_lists => {},
default_attributes => {
nginx => {
port => 80,
@@ -132,6 +133,7 @@ subtest 'role attribute escape dots' => sub {
json_class => 'Chef::Role',
chef_type => 'role',
run_list => [],
+ env_run_lists => {},
default_attributes => {
'nginx.port' => 80,
},
@@ -152,5 +154,38 @@ subtest 'role attribute escape dots' => sub {
or diag explain $thawed;
};
+subtest 'append to / remove from environment runlist' => sub {
+ my $wd=tempd;
+ my $role = Pantry::Model::Role->new(
+ name => "web",
+ _path => "role.json",
+ );
+ $role->append_to_env_run_list( 'test', ["foo", "bar"] );
+ is_deeply([qw/foo bar/], [$role->get_env_run_list('test')->run_list], "append two items to test environment");
+ $role->append_to_env_run_list( 'test', ["baz"] );
+ is_deeply([qw/foo bar baz/], [$role->get_env_run_list('test')->run_list], "append another");
+ $role->remove_from_env_run_list('test', ["bar"]);
+ is_deeply([qw/foo baz/], [$role->get_env_run_list('test')->run_list], "remove from middle");
+ $role->remove_from_run_list('test', ["wibble"]);
+ is_deeply([qw/foo baz/], [$role->get_env_run_list('test')->run_list], "remove item that doesn't exist");
+ $role->save;
+ my $data = _thaw_file("role.json");
+ is_deeply( $data, {
+ name => 'web',
+ json_class => 'Chef::Role',
+ chef_type => 'role',
+ run_list => [],
+ env_run_lists => {
+ test => [qw/foo baz/],
+ },
+ default_attributes => {},
+ override_attributes => {},
+ },
+ "env_run_lists serialized correctly"
+ ) or diag explain $data;
+ ok( my $thawed = Pantry::Model::Role->new_from_file("role.json"), "thawed role");
+ is_deeply([qw/foo baz/], [$thawed->get_env_run_list('test')->run_list], "env_run_lists round-tripped correctly");
+};
+
done_testing;
# COPYRIGHT
View
46 t/privlib/Pantry/App/Command/clidump.pm
@@ -1,46 +0,0 @@
-use v5.14;
-use warnings;
-
-package Pantry::App::Command::clidump;
-# ABSTRACT: dump options as JSON
-# VERSION
-
-use Pantry::App -command;
-use autodie;
-use JSON;
-
-use namespace::clean;
-
-sub abstract {
- return 'dump command line options and remaining args';
-}
-
-sub options {
- my ($self) = @_;
- return $self->data_options;
-}
-
-sub validate {
- return;
-}
-
-sub execute {
- my ($self, $opt, $args) = @_;
- $opt //= {};
- $args //= [];
-
- say JSON->new->utf8->pretty->canonical->encode({
- args => $args,
- opts => { %$opt }, # XXX
- }
- );
- return;
-}
-
-1;
-
-=for Pod::Coverage options validate
-
-=cut
-
-# vim: ts=2 sts=2 sw=2 et:

No commit comments for this range

Something went wrong with that request. Please try again.