diff --git a/apps/automation/ansible/tower/custom/api.pm b/apps/automation/ansible/tower/custom/api.pm index aacfe9a9c..32159fefa 100644 --- a/apps/automation/ansible/tower/custom/api.pm +++ b/apps/automation/ansible/tower/custom/api.pm @@ -142,6 +142,7 @@ sub request_api { my $content = $self->{http}->request( method => defined($options{method}) ? $options{method} : 'GET', url_path => $path, + query_form_post => $options{query_form_post}, unknown_status => $self->{unknown_http_status}, warning_status => $self->{warning_http_status}, critical_status => $self->{critical_http_status} @@ -162,6 +163,8 @@ sub request_api { $self->{output}->option_exit(); } + return $decoded if (defined($options{direct_hash}) && $options{direct_hash} == 1); + push @$results, @{$decoded->{results}}; last if (!defined($decoded->{next})); } @@ -213,6 +216,41 @@ sub tower_list_unified_jobs { return $self->request_api(endpoint => '/unified_jobs/'); } +sub tower_launch_job_template { + my ($self, %options) = @_; + + my $json_request = {}; + $json_request->{inventory} = $options{launch_inventory} if (defined($options{launch_inventory}) && $options{launch_inventory} ne ''); + $json_request->{credential} = $options{launch_credential} if (defined($options{launch_credential})); + $json_request->{job_tags} = $options{launch_tags} if (defined($options{launch_tags})); + $json_request->{limit} = $options{launch_limit} if (defined($options{launch_limit})); + $json_request->{extra_vars} = $options{launch_extra_vars} if (defined($options{launch_extra_vars})); + + my $encoded; + eval { + $encoded = JSON::XS->new->utf8->encode($json_request); + }; + if ($@) { + $self->{output}->add_option_msg(short_msg => 'Cannot encode request: ' . $@); + $self->{output}->option_exit(); + } + + my $job = $self->request_api( + method => 'POST', + force_endpoint => '/job_templates/' . $options{launch_job_template_id} . '/launch/', + query_form_post => $encoded, + direct_hash => 1 + ); + + return $job; +} + +sub tower_get_job { + my ($self, %options) = @_; + + return $self->request_api(force_endpoint => '/jobs/' . $options{job_id} . '/', direct_hash => 1); +} + 1; __END__ diff --git a/apps/automation/ansible/tower/custom/towercli.pm b/apps/automation/ansible/tower/custom/towercli.pm index a14fd0153..ef9134a21 100644 --- a/apps/automation/ansible/tower/custom/towercli.pm +++ b/apps/automation/ansible/tower/custom/towercli.pm @@ -220,6 +220,56 @@ sub tower_list_unified_jobs { $self->{output}->option_exit(); } +sub tower_launch_job_template_set_cmd { + my ($self, %options) = @_; + + return if (defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne ''); + + my $cmd_options = "job launch --job-template=$options{launch_job_template_id} "; + $cmd_options .= " --inventory '$options{launch_inventory}'" if (defined($options{launch_inventory})); + $cmd_options .= " --credential '$options{launch_credential}'" if (defined($options{launch_credential})); + $cmd_options .= " --tags '$options{launch_tags}'" if (defined($options{launch_tags})); + $cmd_options .= " --limit '$options{launch_limit}'" if (defined($options{launch_limit})); + $cmd_options .= " --extra-vars '$options{launch_extra_vars}'" if (defined($options{launch_extra_vars})); + $cmd_options .= ' --insecure --format json'; + $cmd_options .= " --tower-host '$self->{hostname}'" if (defined($self->{hostname})); + $cmd_options .= " --tower-username '$self->{username}'" if (defined($self->{username})); + $cmd_options .= " --tower-password '$self->{password}'" if (defined($self->{password})); + + return $cmd_options; +} + +sub tower_launch_job_template { + my ($self, %options) = @_; + + my $cmd_options = $self->tower_launch_job_template_set_cmd(%options); + my $raw_results = $self->execute(cmd_options => $cmd_options); + + return $raw_results; +} + +sub tower_get_job_set_cmd { + my ($self, %options) = @_; + + return if (defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne ''); + + my $cmd_options = "job get $options{job_id} --insecure --format json"; + $cmd_options .= " --tower-host '$self->{hostname}'" if (defined($self->{hostname})); + $cmd_options .= " --tower-username '$self->{username}'" if (defined($self->{username})); + $cmd_options .= " --tower-password '$self->{password}'" if (defined($self->{password})); + + return $cmd_options; +} + +sub tower_get_job { + my ($self, %options) = @_; + + my $cmd_options = $self->tower_get_job_set_cmd(%options); + my $raw_results = $self->execute(cmd_options => $cmd_options); + + return $raw_results; +} + 1; __END__ diff --git a/apps/automation/ansible/tower/mode/jobtemplates.pm b/apps/automation/ansible/tower/mode/jobtemplates.pm index 88003c607..c0cc2d25f 100644 --- a/apps/automation/ansible/tower/mode/jobtemplates.pm +++ b/apps/automation/ansible/tower/mode/jobtemplates.pm @@ -90,16 +90,61 @@ sub new { bless $self, $class; $options{options}->add_options(arguments => { - 'filter-name:s' => { name => 'filter_name' } + 'filter-name:s' => { name => 'filter_name' }, + 'launch-job-template-id:s' => { name => 'launch_job_template_id' }, + 'launch-extra-vars:s' => { name => 'launch_extra_vars' }, + 'launch-tags:s' => { name => 'launch_tags' }, + 'launch-limit:s' => { name => 'launch_limit' }, + 'launch-inventory:s' => { name => 'launch_inventory' }, + 'launch-credential:s' => { name => 'launch_credential' }, + 'launch-max-retries:s' => { name => 'launch_max_retries', default => 5 }, + 'launch-retry-interval:s' => { name => 'launch_retry_interval', default => 10 } }); return $self; } +sub launch_job { + my ($self, %options) = @_; + + my $job = $options{custom}->tower_launch_job_template( + launch_job_template_id => $self->{option_results}->{launch_job_template_id}, + launch_extra_vars => $self->{option_results}->{launch_extra_vars}, + launch_tags => $self->{option_results}->{launch_tags}, + launch_limit => $self->{option_results}->{launch_limit}, + launch_inventory => $self->{option_results}->{launch_inventory}, + launch_credential => $self->{option_results}->{launch_credential} + ); + + my $job_id = $job->{id}; + my ($job_completed, $retry_idx, $job_result); + $retry_idx = 0; + while (!defined($job_completed) && $retry_idx < $self->{option_results}->{launch_max_retries}) { + sleep($self->{option_results}->{launch_retry_interval}) if ($retry_idx > 0); + $job_result = $options{custom}->tower_get_job(job_id => $job_id); + + $job_completed = $job_result->{finished}; + $retry_idx++; + } + + if ($retry_idx >= $self->{option_results}->{launch_max_retries}) { + $self->{output}->add_option_msg(short_msg => 'cannot get the last job result'); + $self->{output}->option_exit(); + } + + $job->{summary_fields}->{last_job} = $job_result; + return [$job]; +} + sub manage_selection { my ($self, %options) = @_; - my $jobs = $options{custom}->tower_list_job_templates(); + my $jobs; + if (defined($self->{option_results}->{launch_job_template_id}) && $self->{option_results}->{launch_job_template_id} =~ /\d+/) { + $jobs = $self->launch_job(custom => $options{custom}); + } else { + $jobs = $options{custom}->tower_list_job_templates(); + } $self->{global} = { total => 0, failed => 0, successful => 0, canceled => 0, default => 0, pending => 0, running => 0, never => 0 }; $self->{jobtpl} = {}; @@ -136,6 +181,38 @@ Check job templates. Filter job template name (Can use regexp). +=item B<--launch-job-template-id> + +The job_template id to launch. + +=item B<--launch-inventory> + +Specify inventory for job template to run. + +=item B<--launch-credential> + +Specify machine credential for job template to run. + +=item B<--launch-tags> + +Specify tagged actions in the playbook to run. + +=item B<--launch-limit> + +Specify host limit for job template to run. + +=item B<--launch-extra-vars> + +yaml format text that contains extra variables to pass on. + +=item B<--launch-max-retries> + +Number of retries to get job result once launched (Default: 5). + +=item B<--launch-retry-interval> + +Number of seconds between retries (Default : 10). + =item B<--unknown-job-status> Set unknown threshold for status (Default: '%{last_job_status} =~ /default/').