class Resource(models.Resource): cli_help = 'Manage job templates.' endpoint = '/job_templates/' name = models.Field(unique=True) description = models.Field(required=False, display=False) job_type = models.Field( default='run', display=False, show_default=True, type=click.Choice(['run', 'check']), ) inventory = models.Field(type=types.Related('inventory')) project = models.Field(type=types.Related('project')) playbook = models.Field() machine_credential = models.Field('credential', display=False, type=types.Related('credential'), ) cloud_credential = models.Field(type=types.Related('credential'), required=False, display=False) forks = models.Field(type=int, required=False, display=False) limit = models.Field(required=False, display=False) verbosity = models.Field( display=False, type=types.MappedChoice([ (0, 'default'), (1, 'verbose'), (2, 'debug'), ]), ) job_tags = models.Field(required=False, display=False) extra_vars = models.Field(type=models.File('r'), required=False, display=False)
def test_convert(self): """Establish that the convert method converts from the value provided to the user to the internal value, and calls the superclass method. """ mc = types.MappedChoice({'foo': 'bar', 'spam': 'eggs'}) self.assertEqual(mc.convert('bar', 'myopt', None), 'foo') self.assertEqual(mc.convert('eggs', 'myopt', None), 'spam')
class Resource(models.Resource): cli_help = 'Manage credentials within Ansible Tower.' endpoint = '/credentials/' identity = ('user', 'team', 'kind', 'name') name = models.Field(unique=True) description = models.Field(required=False, display=False) # Who owns this credential? user = models.Field( display=False, type=types.Related('user'), required=False, ) team = models.Field( display=True, type=types.Related('team'), required=False, ) # What type of credential is this (machine, SCM, etc.)? kind = models.Field( display=True, help_text='The type of credential being added. ' 'Valid options are: ssh, scm, aws, rax, vmware,' ' gce, azure, openstack.', type=click.Choice([ 'ssh', 'scm', 'aws', 'rax', 'vmware', 'gce', 'azure', 'openstack' ]), ) # need host in order to use VMware host = models.Field(help_text='The hostname or IP address to use.', required=False, display=False) # need project to use openstack project = models.Field(help_text='The identifier for the project.', required=False, display=False) # SSH and SCM fields. username = models.Field( help_text='The username. For AWS credentials, the access key.', required=False, ) password = models.Field( help_text='The password. For AWS credentials, the secret key. ' 'For Rackspace credentials, the API key.', password=True, required=False, ) ssh_key_data = models.Field( 'ssh_key_data', display=False, help_text="The full path to the SSH private key to store. " "(Don't worry; it's encrypted.)", required=False, type=models.File('r'), ) ssh_key_unlock = models.Field('ssh_key_unlock', password=True, required=False) # Method with which to esclate become_method = models.Field( help_text='Privledge escalation method. ', type=types.MappedChoice([ ('', 'None'), ('sudo', 'sudo'), ('su', 'su'), ('pbrun', 'pbrun'), ('pfexec', 'pfexec'), ]), required=False, ) # SSH specific fields. become_username = models.Field(required=False, display=False) become_password = models.Field(password=True, required=False) vault_password = models.Field(password=True, required=False)
class Resource(models.Resource, models.MonitorableResource): cli_help = 'Manage projects within Ansible Tower.' endpoint = '/projects/' unified_job_type = '/project_updates/' name = models.Field(unique=True) description = models.Field(required=False, display=False) organization = models.Field(type=types.Related('organization'), display=False, required=False) scm_type = models.Field( type=types.MappedChoice([ ('', 'manual'), ('git', 'git'), ('hg', 'hg'), ('svn', 'svn'), ]), ) scm_url = models.Field(required=False) local_path = models.Field( help_text='For manual projects, the server playbook directory name', required=False) scm_branch = models.Field(required=False, display=False) scm_credential = models.Field( 'credential', display=False, required=False, type=types.Related('credential'), ) scm_clean = models.Field(type=bool, required=False, display=False) scm_delete_on_update = models.Field(type=bool, required=False, display=False) scm_update_on_launch = models.Field(type=bool, required=False, display=False) job_timeout = models.Field(type=int, required=False, display=False, help_text='The timeout field (in seconds).') @resources.command @click.option('--monitor', is_flag=True, default=False, help='If sent, immediately calls `project monitor` on the ' 'project rather than exiting with a success.' 'It polls for status until the SCM is updated.') @click.option('--wait', is_flag=True, default=False, help='Polls server for status, exists when finished.') @click.option('--timeout', required=False, type=int, help='If provided with --monitor, the SCM update' ' will time out after the given number of seconds. ' 'Does nothing if --monitor is not sent.') def create(self, organization=None, monitor=False, wait=False, timeout=None, fail_on_found=False, force_on_exists=False, **kwargs): """Create a new item of resource, with or w/o org. This would be a shared class with user, but it needs the ability to monitor if the flag is set. """ if 'job_timeout' in kwargs and 'timeout' not in kwargs: kwargs['timeout'] = kwargs.pop('job_timeout') post_associate = False if organization: # Processing the organization flag depends on version debug.log('Checking Organization Relationship.', header='details') r = client.options('/projects/') if 'organization' in r.json()['actions']['POST']: kwargs['organization'] = organization else: post_associate = True # First, run the create method, ignoring the organization given answer = super(Resource, self).write( create_on_missing=True, fail_on_found=fail_on_found, force_on_exists=force_on_exists, **kwargs ) project_id = answer['id'] # If an organization is given, associate it here if post_associate: # Get the organization from Tower, will lookup name if needed org_resource = get_resource('organization') org_data = org_resource.get(organization) org_pk = org_data['id'] debug.log("associating the project with its organization", header='details', nl=1) org_resource._assoc('projects', org_pk, project_id) # if the monitor flag is set, wait for the SCM to update if monitor and answer.get('changed', False): return self.monitor(pk=None, parent_pk=project_id, timeout=timeout) elif wait and answer.get('changed', False): return self.wait(pk=None, parent_pk=project_id, timeout=timeout) return answer @resources.command(use_fields_as_options=( 'name', 'description', 'scm_type', 'scm_url', 'local_path', 'scm_branch', 'scm_credential', 'scm_clean', 'scm_delete_on_update', 'scm_update_on_launch', 'job_timeout' )) def modify(self, pk=None, create_on_missing=False, **kwargs): """Modify an already existing. To edit the project's organizations, see help for organizations. Fields in the resource's `identity` tuple can be used in lieu of a primary key for a lookup; in such a case, only other fields are written. To modify unique fields, you must use the primary key for the lookup. """ # Associated with issue #52, the organization can't be modified # with the 'modify' command. This would create confusion about # whether its flag is an identifier versus a field to modify. if 'job_timeout' in kwargs and 'timeout' not in kwargs: kwargs['timeout'] = kwargs.pop('job_timeout') return super(Resource, self).write( pk, create_on_missing=create_on_missing, force_on_exists=True, **kwargs ) @resources.command(use_fields_as_options=('name', 'organization')) @click.option('--monitor', is_flag=True, default=False, help='If sent, immediately calls `job monitor` on the newly ' 'launched job rather than exiting with a success.') @click.option('--wait', is_flag=True, default=False, help='Polls server for status, exists when finished.') @click.option('--timeout', required=False, type=int, help='If provided with --monitor, this command (not the job)' ' will time out after the given number of seconds. ' 'Does nothing if --monitor is not sent.') def update(self, pk=None, create_on_missing=False, monitor=False, wait=False, timeout=None, name=None, organization=None): """Trigger a project update job within Ansible Tower. Only meaningful on non-manual projects. """ # First, get the appropriate project. # This should be uniquely identified at this point, and if not, then # we just want the error that `get` will throw to bubble up. project = self.get(pk, name=name, organization=organization) pk = project['id'] # Determine whether this project is able to be updated. debug.log('Asking whether the project can be updated.', header='details') result = client.get('/projects/%d/update/' % pk) if not result.json()['can_update']: raise exc.CannotStartJob('Cannot update project.') # Okay, this project can be updated, according to Tower. # Commence the update. debug.log('Updating the project.', header='details') result = client.post('/projects/%d/update/' % pk) # If we were told to monitor the project update's status, do so. if monitor: project_update_id = result.json()['project_update'] return self.monitor(project_update_id, parent_pk=pk, timeout=timeout) elif wait: project_update_id = result.json()['project_update'] return self.wait(project_update_id, parent_pk=pk, timeout=timeout) # Return the project update ID. return { 'changed': True, } @resources.command @click.option('--detail', is_flag=True, default=False, help='Print more detail.') def status(self, pk=None, detail=False, **kwargs): """Print the status of the most recent update.""" # Obtain the most recent project update job = self.last_job_data(pk, **kwargs) # In most cases, we probably only want to know the status of the job # and the amount of time elapsed. However, if we were asked for # verbose information, provide it. if detail: return job # Print just the information we need. return { 'elapsed': job['elapsed'], 'failed': job['failed'], 'status': job['status'], }
class Resource(models.SurveyResource): cli_help = 'Manage job templates.' endpoint = '/job_templates/' name = models.Field(unique=True) description = models.Field(required=False, display=False) job_type = models.Field( required=False, display=False, type=click.Choice(['run', 'check', 'scan']), ) inventory = models.Field(type=types.Related('inventory'), required=False) project = models.Field(type=types.Related('project')) playbook = models.Field() machine_credential = models.Field( 'credential', display=False, required=False, type=types.Related('credential'), ) cloud_credential = models.Field(type=types.Related('credential'), required=False, display=False) network_credential = models.Field(type=types.Related('credential'), required=False, display=False) forks = models.Field(type=int, required=False, display=False) limit = models.Field(required=False, display=False) verbosity = models.Field( display=False, type=types.MappedChoice([ (0, 'default'), (1, 'verbose'), (2, 'more_verbose'), (3, 'debug'), (4, 'connection'), (5, 'winrm'), ]), required=False, ) job_tags = models.Field(required=False, display=False) skip_tags = models.Field(required=False, display=False) extra_vars = models.Field( type=types.Variables(), required=False, display=False, multiple=True, help_text='Extra variables used by Ansible in YAML or key=value ' 'format. Use @ to get YAML from a file.') host_config_key = models.Field( required=False, display=False, help_text='Allow Provisioning Callbacks using this host config key') ask_variables_on_launch = models.Field( type=bool, required=False, display=False, help_text='Prompt user for extra_vars on launch.') ask_limit_on_launch = models.Field( type=bool, required=False, display=False, help_text='Prompt user for host limits on launch.') ask_tags_on_launch = models.Field( type=bool, required=False, display=False, help_text='Prompt user for job tags on launch.') ask_skip_tags_on_launch = models.Field( type=bool, required=False, display=False, help_text='Prompt user for tags to skip on launch.') ask_job_type_on_launch = models.Field( type=bool, required=False, display=False, help_text='Prompt user for job type on launch.') ask_inventory_on_launch = models.Field( type=bool, required=False, display=False, help_text='Prompt user for inventory on launch.') ask_credential_on_launch = models.Field( type=bool, required=False, display=False, help_text='Prompt user for machine credential on launch.') become_enabled = models.Field(type=bool, required=False, display=False) timeout = models.Field(type=int, required=False, display=False, help_text='The timeout field (in seconds).') survey_enabled = models.Field( type=bool, required=False, display=False, help_text='Prompt user for job type on launch.') survey_spec = models.Field( type=types.Variables(), required=False, display=False, help_text='On write commands, perform extra POST to the ' 'survey_spec endpoint.') @resources.command def create(self, fail_on_found=False, force_on_exists=False, extra_vars=None, **kwargs): """Create a job template.""" # Provide a default value for job_type, but only in creation of JT if not kwargs.get('job_type', False): kwargs['job_type'] = 'run' return super(Resource, self).create(fail_on_found=fail_on_found, force_on_exists=force_on_exists, **kwargs) @resources.command(use_fields_as_options=False) @click.option('--job-template', type=types.Related('job_template')) @click.option('--label', type=types.Related('label')) def associate_label(self, job_template, label): """Associate an label with this job template.""" return self._assoc('labels', job_template, label) @resources.command(use_fields_as_options=False) @click.option('--job-template', type=types.Related('job_template')) @click.option('--label', type=types.Related('label')) def disassociate_label(self, job_template, label): """Disassociate an label from this job template.""" return self._disassoc('labels', job_template, label) @resources.command(use_fields_as_options=False) @click.option('--job-template', type=types.Related('job_template')) @click.option('--notification-template', type=types.Related('notification_template')) @click.option('--status', type=click.Choice(['any', 'error', 'success']), required=False, default='any', help='Specify job run status' ' of job template to relate to.') def associate_notification_template(self, job_template, notification_template, status): """Associate a notification template from this job template.""" return self._assoc('notification_templates_%s' % status, job_template, notification_template) @resources.command(use_fields_as_options=False) @click.option('--job-template', type=types.Related('job_template')) @click.option('--notification-template', type=types.Related('notification_template')) @click.option('--status', type=click.Choice(['any', 'error', 'success']), required=False, default='any', help='Specify job run status' ' of job template to relate to.') def disassociate_notification_template(self, job_template, notification_template, status): """Disassociate a notification template from this job template.""" return self._disassoc('notification_templates_%s' % status, job_template, notification_template)
class Resource(models.Resource): cli_help = 'Manage credentials within Ansible Tower.' endpoint = '/credentials/' identity = ('organization', 'user', 'team', 'kind', 'name') name = models.Field(unique=True) description = models.Field(required=False, display=False) # Who owns this credential? user = models.Field( display=False, type=types.Related('user'), required=False, ) team = models.Field( display=False, type=types.Related('team'), required=False, ) organization = models.Field( display=False, type=types.Related('organization'), required=False, ) # What type of credential is this (machine, SCM, etc.)? kind = models.Field( display=True, help_text='The type of credential being added. ' 'Valid options are: ssh, net, scm, aws, rax, vmware,' ' satellite6, cloudforms, gce, azure, azure_rm, openstack.', type=click.Choice([ 'ssh', 'net', 'scm', 'aws', 'rax', 'vmware', 'satellite6', 'cloudforms', 'gce', 'azure', 'azure_rm', 'openstack' ]), ) # need host in order to use VMware host = models.Field(help_text='The hostname or IP address to use.', required=False, display=False) # need project to use openstack project = models.Field(help_text='The identifier for the project.', required=False, display=False) # SSH and SCM fields. username = models.Field( help_text='The username. For AWS credentials, the access key.', required=False, ) password = models.Field( help_text='%sThe password. For AWS credentials, the secret key. ' 'For Rackspace credentials, the API key.' % PROMPT, password=True, required=False, ) ssh_key_data = models.Field( 'ssh_key_data', display=False, help_text="The full path to the SSH private key to store. " "(Don't worry; it's encrypted.)", required=False, type=models.File('r'), ) ssh_key_unlock = models.Field(help_text='%sssh_key_unlock' % PROMPT, password=True, required=False) # Extra fields in 3.0 authorize = models.Field( help_text='Whether to use the authorize mechanism when type is "net".', required=False, display=False, type=click.BOOL, ) authorize_password = models.Field( help_text='Password used by the authorize mechanism when type is ' '"net".', password=True, required=False, display=False, ) client = models.Field( help_text='Client Id or Application Id for the credential when type ' 'is "azure_rm".', required=False, display=False, ) secret = models.Field( help_text='Secret Token for this credential when type is "azure_rm".', required=False, display=False) subscription = models.Field( help_text='Subscription identifier for this credential when type is ' '"azure_rm".', required=False, display=False, ) tenant = models.Field( help_text='Tenant identifier for this credential when type is ' '"azure_rm"', required=False, display=False, ) domain = models.Field( help_text='Domain name for this credential when type is "openstack".', required=False, display=False, ) # Method with which to esclate become_method = models.Field( display=False, help_text='Privledge escalation method. ', type=types.MappedChoice([ ('', 'None'), ('sudo', 'sudo'), ('su', 'su'), ('pbrun', 'pbrun'), ('pfexec', 'pfexec'), ]), required=False, ) # SSH specific fields. become_username = models.Field(required=False, display=False) become_password = models.Field(password=True, required=False, help_text='%sThe become_password field' % PROMPT) vault_password = models.Field(password=True, required=False, help_text='%sThe vault_password field' % PROMPT) @resources.command def create(self, **kwargs): """Create a credential. """ if (kwargs.get('user', False) or kwargs.get('team', False) or kwargs.get('organization', False)): debug.log('Checking Project API Details.', header='details') r = client.options('/credentials/') if 'organization' in r.json()['actions']['POST']: for i in range(len(self.fields)): if self.fields[i].name in ('user', 'team'): self.fields[i].no_lookup = True return super(Resource, self).create(**kwargs)
class Resource(models.ExeResource): """A resource for ad hoc commands.""" cli_help = 'Launch commands based on playbook given at runtime.' endpoint = '/ad_hoc_commands/' # Parameters similar to job job_explanation = models.Field(required=False, display=False) created = models.Field(required=False, display=True) status = models.Field(required=False, display=True) elapsed = models.Field(required=False, display=True) # Parameters similar to job_template job_type = models.Field( default='run', display=False, show_default=True, type=click.Choice(['run', 'check']), ) inventory = models.Field(type=types.Related('inventory')) machine_credential = models.Field( 'credential', display=False, type=types.Related('credential'), ) cloud_credential = models.Field(type=types.Related('credential'), required=False, display=False) module_name = models.Field(required=False, display=True, default="command", show_default=True) module_args = models.Field(required=False, display=False) forks = models.Field(type=int, required=False, display=False) limit = models.Field(required=False, display=False) verbosity = models.Field( display=False, type=types.MappedChoice([ (0, 'default'), (1, 'verbose'), (2, 'more_verbose'), (3, 'debug'), (4, 'connection'), (5, 'winrm'), ]), required=False, ) @resources.command(use_fields_as_options=( 'job_explanation', 'job_type', 'inventory', 'machine_credential', 'cloud_credential', 'module_name', 'module_args', 'forks', 'limit', 'verbosity', 'become_enabled', )) @click.option('--monitor', is_flag=True, default=False, help='If sent, immediately calls `monitor` on the newly ' 'launched command rather than exiting with a success.') @click.option('--timeout', required=False, type=int, help='If provided with --monitor, this attempt' ' will time out after the given number of seconds. ' 'Does nothing if --monitor is not sent.') @click.option('--become', required=False, is_flag=True, help='If used, privledge escalation will be enabled for ' 'this command.') def launch(self, monitor=False, timeout=None, become=False, **kwargs): """Launch a new ad-hoc command. Runs a user-defined command from Ansible Tower, immediately starts it, and returns back an ID in order for its status to be monitored. """ # This feature only exists for versions 2.2 and up r = client.get('/') if 'ad_hoc_commands' not in r.json(): raise exc.TowerCLIError('Your host is running an outdated version' 'of Ansible Tower that can not run ' 'ad-hoc commands (2.2 or earlier)') # Pop the None arguments because we have no .write() method in # inheritance chain for this type of resource. This is needed self._pop_none(kwargs) # Change the flag to the dictionary format if become: kwargs['become_enabled'] = True # Actually start the command. debug.log('Launching the ad-hoc command.', header='details') result = client.post(self.endpoint, data=kwargs) command = result.json() command_id = command['id'] # If we were told to monitor the command once it started, then call # monitor from here. if monitor: return self.monitor(command_id, timeout=timeout) # Return the command ID and other response data answer = OrderedDict(( ('changed', True), ('id', command_id), )) answer.update(result.json()) return answer
class Resource(models.MonitorableResource): cli_help = 'Manage projects within Ansible Tower.' endpoint = '/projects/' name = models.Field(unique=True) description = models.Field(required=False, display=False) organization = models.Field(type=types.Related('organization'), display=False) scm_type = models.Field(type=types.MappedChoice([ ('', 'manual'), ('git', 'git'), ('hg', 'hg'), ('svn', 'svn'), ]), ) scm_url = models.Field(required=False) scm_branch = models.Field(required=False, display=False) scm_credential = models.Field( 'credential', display=False, required=False, type=types.Related('credential'), ) scm_clean = models.Field(type=bool, required=False, display=False) scm_delete_on_update = models.Field(type=bool, required=False, display=False) scm_update_on_launch = models.Field(type=bool, required=False, display=False) @resources.command(use_fields_as_options=('name', 'organization')) @click.option('--monitor', is_flag=True, default=False, help='If sent, immediately calls `job monitor` on the newly ' 'launched job rather than exiting with a success.') @click.option('--timeout', required=False, type=int, help='If provided with --monitor, this command (not the job)' ' will time out after the given number of seconds. ' 'Does nothing if --monitor is not sent.') def update(self, pk, monitor=False, timeout=None, name=None, organization=None): """Trigger a project update job within Ansible Tower. Only meaningful on non-manual projects. """ # First, get the appropriate project. # This should be uniquely identified at this point, and if not, then # we just want the error that `get` will throw to bubble up. project = self.get(pk, name=name, organization=organization) pk = project['id'] # Determine whether this project is able to be updated. debug.log('Asking whether the project can be updated.', header='details') result = client.get('/projects/%d/update/' % pk) if not result.json()['can_update']: raise exc.CannotStartJob('Cannot update project.') # Okay, this project can be updated, according to Tower. # Commence the update. debug.log('Updating the project.', header='details') result = client.post('/projects/%d/update/' % pk) project_update_id = result.json()['project_update'] # If we were told to monitor the project update's status, do so. if monitor: return self.monitor(pk, timeout=timeout) # Return the project update ID. return { 'changed': True, } @resources.command @click.option('--detail', is_flag=True, default=False, help='Print more detail.') def status(self, pk, detail=False): """Print the current job status.""" # Get the job from Ansible Tower. debug.log('Asking for project update status.', header='details') project = client.get('/projects/%d/' % pk).json() # Determine the appropriate project update. if 'current_update' in project['related']: debug.log('A current update exists; retrieving it.', header='details') job = client.get(project['related']['current_update'][7:]).json() elif project['related'].get('last_update', None): debug.log( 'No current update exists; retrieving the most ' 'recent update.', header='details') job = client.get(project['related']['last_update'][7:]).json() else: raise exc.NotFound('No project updates exist.') # In most cases, we probably only want to know the status of the job # and the amount of time elapsed. However, if we were asked for # verbose information, provide it. if detail: return job # Print just the information we need. return adict({ 'elapsed': job['elapsed'], 'failed': job['failed'], 'status': job['status'], })
class Resource(models.Resource): cli_help = 'Manage job templates.' endpoint = '/job_templates/' name = models.Field(unique=True) description = models.Field(required=False, display=False) job_type = models.Field( display=False, type=click.Choice(['run', 'check', 'scan']), ) inventory = models.Field(type=types.Related('inventory'), required=False) project = models.Field(type=types.Related('project')) playbook = models.Field() machine_credential = models.Field( 'credential', display=False, required=False, type=types.Related('credential'), ) cloud_credential = models.Field(type=types.Related('credential'), required=False, display=False) network_credential = models.Field(type=types.Related('credential'), required=False, display=False) forks = models.Field(type=int, required=False, display=False) limit = models.Field(required=False, display=False) verbosity = models.Field( display=False, type=types.MappedChoice([ (0, 'default'), (1, 'verbose'), (2, 'debug'), ]), required=False, ) job_tags = models.Field(required=False, display=False) skip_tags = models.Field(required=False, display=False) extra_vars = models.Field(required=False, display=False) ask_variables_on_launch = models.Field( type=bool, required=False, display=False, help_text='Prompt user for extra_vars on launch.') ask_limit_on_launch = models.Field( type=bool, required=False, display=False, help_text='Prompt user for host limits on launch.') ask_tags_on_launch = models.Field( type=bool, required=False, display=False, help_text='Prompt user for job tags on launch.') ask_job_type_on_launch = models.Field( type=bool, required=False, display=False, help_text='Prompt user for job type on launch.') ask_inventory_on_launch = models.Field( type=bool, required=False, display=False, help_text='Prompt user for inventory on launch.') ask_credential_on_launch = models.Field( type=bool, required=False, display=False, help_text='Prompt user for machine credential on launch.') become_enabled = models.Field(type=bool, required=False, display=False) @click.option('--extra-vars', required=False, multiple=True, help='Extra variables used by Ansible in YAML or key=value ' 'format. Use @ to get YAML from a file.') def create(self, fail_on_found=False, force_on_exists=False, extra_vars=None, **kwargs): """Create a job template. You may include multiple --extra-vars flags in order to combine different sources of extra variables. Start this with @ in order to indicate a filename.""" if extra_vars: # combine sources of extra variables, if given kwargs['extra_vars'] = parser.process_extra_vars(extra_vars, force_json=False) # Provide a default value for job_type, but only in creation of JT if not kwargs.get('job_type', False): kwargs['job_type'] = 'run' return super(Resource, self).create(fail_on_found=fail_on_found, force_on_exists=force_on_exists, **kwargs) @click.option('--extra-vars', required=False, multiple=True, help='Extra variables used by Ansible in YAML or key=value ' 'format. Use @ to get YAML from a file.') def modify(self, pk=None, create_on_missing=False, extra_vars=None, **kwargs): """Modify a job template. You may include multiple --extra-vars flags in order to combine different sources of extra variables. Start this with @ in order to indicate a filename.""" if extra_vars: # combine sources of extra variables, if given kwargs['extra_vars'] = parser.process_extra_vars(extra_vars, force_json=False) return super(Resource, self).modify(pk=pk, create_on_missing=create_on_missing, **kwargs) @resources.command(use_fields_as_options=False) @click.option('--job-template', type=types.Related('job_template')) @click.option('--label', type=types.Related('label')) def associate_label(self, job_template, label): """Associate an label with this job template.""" return self._assoc('labels', job_template, label) @resources.command(use_fields_as_options=False) @click.option('--job-template', type=types.Related('job_template')) @click.option('--label', type=types.Related('label')) def disassociate_label(self, job_template, label): """Disassociate an label from this job template.""" return self._disassoc('labels', job_template, label) @resources.command(use_fields_as_options=False) @click.option('--job-template', type=types.Related('job_template')) @click.option('--notification-template', type=types.Related('notification_template')) @click.option('--status', type=click.Choice(['any', 'error', 'success']), required=False, default='any', help='Specify job run status' ' of job template to relate to.') def associate_notification_template(self, job_template, notification_template, status): """Associate a notification template from this job template.""" return self._assoc('notification_templates_%s' % status, job_template, notification_template) @resources.command(use_fields_as_options=False) @click.option('--job-template', type=types.Related('job_template')) @click.option('--notification-template', type=types.Related('notification_template')) @click.option('--status', type=click.Choice(['any', 'error', 'success']), required=False, default='any', help='Specify job run status' ' of job template to relate to.') def disassociate_notification_template(self, job_template, notification_template, status): """Disassociate a notification template from this job template.""" return self._disassoc('notification_templates_%s' % status, job_template, notification_template)
class Resource(models.Resource): cli_help = 'Manage job templates.' endpoint = '/job_templates/' name = models.Field(unique=True) description = models.Field(required=False, display=False) job_type = models.Field( display=False, type=click.Choice(['run', 'check']), ) inventory = models.Field(type=types.Related('inventory')) project = models.Field(type=types.Related('project')) playbook = models.Field() machine_credential = models.Field( 'credential', display=False, type=types.Related('credential'), ) cloud_credential = models.Field(type=types.Related('credential'), required=False, display=False) forks = models.Field(type=int, required=False, display=False) limit = models.Field(required=False, display=False) verbosity = models.Field( display=False, type=types.MappedChoice([ (0, 'default'), (1, 'verbose'), (2, 'debug'), ]), required=False, ) job_tags = models.Field(required=False, display=False) skip_tags = models.Field(required=False, display=False) extra_vars = models.Field(required=False, display=False) ask_variables_on_launch = models.Field( type=bool, required=False, display=False, help_text='Prompt user for extra_vars on launch.') become_enabled = models.Field(type=bool, required=False, display=False) @click.option('--extra-vars', required=False, multiple=True, help='Extra variables used by Ansible in YAML or key=value ' 'format. Use @ to get YAML from a file.') def create(self, fail_on_found=False, force_on_exists=False, extra_vars=None, **kwargs): """Create a job template. You may include multiple --extra-vars flags in order to combine different sources of extra variables. Start this with @ in order to indicate a filename.""" if extra_vars: # combine sources of extra variables, if given kwargs['extra_vars'] = parser.process_extra_vars(extra_vars, force_json=False) # Provide a default value for job_type, but only in creation of JT if not kwargs.get('job_type', False): kwargs['job_type'] = 'run' return super(Resource, self).create(fail_on_found=fail_on_found, force_on_exists=force_on_exists, **kwargs) @click.option('--extra-vars', required=False, multiple=True, help='Extra variables used by Ansible in YAML or key=value ' 'format. Use @ to get YAML from a file.') def modify(self, pk=None, create_on_missing=False, extra_vars=None, **kwargs): """Modify a job template. You may include multiple --extra-vars flags in order to combine different sources of extra variables. Start this with @ in order to indicate a filename.""" if extra_vars: # combine sources of extra variables, if given kwargs['extra_vars'] = parser.process_extra_vars(extra_vars, force_json=False) return super(Resource, self).modify(pk=pk, create_on_missing=create_on_missing, **kwargs)