Merge remote-tracking branch 'origin/master' into auditlog

* origin/master:
  AC-637 Credential now requires scm_key_unlock when saving encrypted ssh_key_data.
  AC-626 Removed support for prompting for password and ssh_key_unlock for scm/cloud credentials.
  AC-613 Change rackspace to rax for inventory source field value.
  AC-613 Change rackspace to rax for inventory source field value.
  AC-624 Fix options docs for project update view.
  AC-632 Fix escaping for ansible-playbook command line when also using ssh-agent.
  Update CONTRIBUTING.md
  AC-630 Expose cloud_credentials field for job template and job.
  AC-641 Added pattern to respond to key unlock prompt for project update.
  Updated all vendored third-party packages.
  AC-636 Fix existing projects with scm_type=null to always use empty string. Update validation and tests to ensure None gets automatically coerced to an empty string on saving a project.
  AC-633 js error fixed.
  AC-633 fixed a sort of unrelated js error. The capitalize filter directive attempted to act on a 'null' input error. Added a test to ignore empty/null input.
  AC-633 Fixed 'hast' typo.
  AC-617 changed callback generation icon to a magic wand, which will hopefully satiate jlaska.
  AC-627 Fixed password/ssh_password collision in Credentials.js form. This was also fixed in auditlog branch.
  AC-628 applied credential changes made in add controller to edit controller so that credential/cloud_credential lookups display context-aware  credential lists.
  Moved credentials in tab order. It now follows teams and precedes projects. Based on a suggestion from jlaska.
  AC-609 Fixed issue with help button not displaying correctly on 'select' pages where user can pick an existing object (i.e. users, credentials, etc) to add to a parent object.

Conflicts:
	awx/api/serializers.py
	awx/main/migrations/0025_v14_changes.py
This commit is contained in:
Matthew Jones
2013-11-18 09:18:37 -05:00
797 changed files with 46286 additions and 28659 deletions

View File

@@ -96,6 +96,7 @@ class ChoiceField(fields.ChoiceField):
# ModelSerializer.
serializers.ChoiceField = ChoiceField
class BaseSerializer(serializers.ModelSerializer):
# add the URL and related resources
@@ -187,10 +188,6 @@ class BaseSerializer(serializers.ModelSerializer):
else:
return obj.active
def validate_description(self, attrs, source):
# Description should always be empty string, never null.
attrs[source] = attrs.get(source, None) or ''
return attrs
class UserSerializer(BaseSerializer):
@@ -278,6 +275,7 @@ class UserSerializer(BaseSerializer):
def validate_is_superuser(self, attrs, source):
return self._validate_ldap_managed_field(attrs, source)
class OrganizationSerializer(BaseSerializer):
class Meta:
@@ -299,6 +297,7 @@ class OrganizationSerializer(BaseSerializer):
))
return res
class ProjectSerializer(BaseSerializer):
playbooks = serializers.Field(source='playbooks', help_text='Array of playbooks available within this project.')
@@ -334,27 +333,32 @@ class ProjectSerializer(BaseSerializer):
args=(obj.last_update.pk,))
return res
def _get_scm_type(self, attrs, source=None):
if self.object:
return attrs.get(source or 'scm_type', self.object.scm_type) or u''
else:
return attrs.get(source or 'scm_type', u'') or u''
def validate_local_path(self, attrs, source):
# Don't allow assigning a local_path used by another project.
# Don't allow assigning a local_path when scm_type is set.
valid_local_paths = Project.get_local_path_choices()
if self.object:
scm_type = attrs.get('scm_type', self.object.scm_type)
if not scm_type:
valid_local_paths.append(self.object.local_path)
else:
scm_type = attrs.get('scm_type', '')
scm_type = self._get_scm_type(attrs)
if self.object and not scm_type:
valid_local_paths.append(self.object.local_path)
if scm_type:
attrs.pop(source, None)
if source in attrs and attrs[source] not in valid_local_paths:
raise serializers.ValidationError('Invalid path choice')
return attrs
def validate_scm_type(self, attrs, source):
scm_type = self._get_scm_type(attrs, source)
attrs[source] = scm_type
return attrs
def validate_scm_url(self, attrs, source):
if self.object:
scm_type = attrs.get('scm_type', self.object.scm_type) or ''
else:
scm_type = attrs.get('scm_type', '') or ''
scm_type = self._get_scm_type(attrs)
scm_url = unicode(attrs.get(source, None) or '')
if not scm_type:
return attrs
@@ -413,6 +417,7 @@ class ProjectSerializer(BaseSerializer):
# FIXME: Validate combination of SCM URL and credential!
class ProjectPlaybooksSerializer(ProjectSerializer):
class Meta:
@@ -423,6 +428,7 @@ class ProjectPlaybooksSerializer(ProjectSerializer):
ret = super(ProjectPlaybooksSerializer, self).to_native(obj)
return ret.get('playbooks', [])
class ProjectUpdateSerializer(BaseSerializer):
class Meta:
@@ -441,6 +447,7 @@ class ProjectUpdateSerializer(BaseSerializer):
))
return res
class BaseSerializerWithVariables(BaseSerializer):
def validate_variables(self, attrs, source):
@@ -453,6 +460,7 @@ class BaseSerializerWithVariables(BaseSerializer):
raise serializers.ValidationError('Must be valid JSON or YAML')
return attrs
class InventorySerializer(BaseSerializerWithVariables):
class Meta:
@@ -481,6 +489,7 @@ class InventorySerializer(BaseSerializerWithVariables):
))
return res
class HostSerializer(BaseSerializerWithVariables):
class Meta:
@@ -611,6 +620,7 @@ class GroupSerializer(BaseSerializerWithVariables):
raise serializers.ValidationError('Invalid group name')
return attrs
class GroupTreeSerializer(GroupSerializer):
children = serializers.SerializerMethodField('get_children')
@@ -628,6 +638,7 @@ class GroupTreeSerializer(GroupSerializer):
children_qs = obj.children.filter(active=True)
return GroupTreeSerializer(children_qs, many=True).data
class BaseVariableDataSerializer(BaseSerializer):
def to_native(self, obj):
@@ -643,24 +654,28 @@ class BaseVariableDataSerializer(BaseSerializer):
data = {'variables': json.dumps(data)}
return super(BaseVariableDataSerializer, self).from_native(data, files)
class InventoryVariableDataSerializer(BaseVariableDataSerializer):
class Meta:
model = Inventory
fields = ('variables',)
class HostVariableDataSerializer(BaseVariableDataSerializer):
class Meta:
model = Host
fields = ('variables',)
class GroupVariableDataSerializer(BaseVariableDataSerializer):
class Meta:
model = Group
fields = ('variables',)
class InventorySourceSerializer(BaseSerializer):
#source_password = serializers.WritableField(required=False, default='')
@@ -730,6 +745,7 @@ class InventorySourceSerializer(BaseSerializer):
# FIXME
return attrs
class InventoryUpdateSerializer(BaseSerializer):
class Meta:
@@ -749,6 +765,7 @@ class InventoryUpdateSerializer(BaseSerializer):
))
return res
class TeamSerializer(BaseSerializer):
class Meta:
@@ -768,6 +785,7 @@ class TeamSerializer(BaseSerializer):
))
return res
class PermissionSerializer(BaseSerializer):
class Meta:
@@ -789,6 +807,7 @@ class PermissionSerializer(BaseSerializer):
res['inventory'] = reverse('api:inventory_detail', args=(obj.inventory.pk,))
return res
def validate(self, attrs):
# Can only set either user or team.
if attrs['user'] and attrs['team']:
@@ -804,6 +823,7 @@ class PermissionSerializer(BaseSerializer):
'assigning deployment permissions')
return attrs
class CredentialSerializer(BaseSerializer):
# FIXME: may want to make some of these filtered based on user accessing
@@ -845,13 +865,15 @@ class CredentialSerializer(BaseSerializer):
res['team'] = reverse('api:team_detail', args=(obj.team.pk,))
return res
class JobTemplateSerializer(BaseSerializer):
class Meta:
model = JobTemplate
fields = BASE_FIELDS + ('job_type', 'inventory', 'project', 'playbook',
'credential', 'forks', 'limit', 'verbosity',
'extra_vars', 'job_tags', 'host_config_key')
'credential', 'cloud_credential', 'forks',
'limit', 'verbosity', 'extra_vars', 'job_tags',
'host_config_key')
def get_related(self, obj):
if obj is None:
@@ -864,6 +886,9 @@ class JobTemplateSerializer(BaseSerializer):
))
if obj.credential:
res['credential'] = reverse('api:credential_detail', args=(obj.credential.pk,))
if obj.cloud_credential:
res['cloud_credential'] = reverse('api:credential_detail',
args=(obj.cloud_credential.pk,))
if obj.host_config_key:
res['callback'] = reverse('api:job_template_callback', args=(obj.pk,))
return res
@@ -875,6 +900,7 @@ class JobTemplateSerializer(BaseSerializer):
raise serializers.ValidationError('Playbook not found for project')
return attrs
class JobSerializer(BaseSerializer):
passwords_needed_to_start = serializers.Field(source='passwords_needed_to_start')
@@ -883,7 +909,7 @@ class JobSerializer(BaseSerializer):
model = Job
fields = ('id', 'url', 'related', 'summary_fields', 'created',
'modified', 'job_template', 'job_type', 'inventory',
'project', 'playbook', 'credential',
'project', 'playbook', 'credential', 'cloud_credential',
'forks', 'limit', 'verbosity', 'extra_vars',
'job_tags', 'launch_type', 'status', 'failed',
'result_stdout', 'result_traceback',
@@ -903,6 +929,9 @@ class JobSerializer(BaseSerializer):
))
if obj.job_template:
res['job_template'] = reverse('api:job_template_detail', args=(obj.job_template.pk,))
if obj.cloud_credential:
res['cloud_credential'] = reverse('api:credential_detail',
args=(obj.cloud_credential.pk,))
if obj.can_start or True:
res['start'] = reverse('api:job_start', args=(obj.pk,))
if obj.can_cancel or True:
@@ -925,6 +954,8 @@ class JobSerializer(BaseSerializer):
data.setdefault('playbook', job_template.playbook)
if job_template.credential:
data.setdefault('credential', job_template.credential.pk)
if job_template.cloud_credential:
data.setdefault('cloud_credential', job_template.cloud_credential.pk)
data.setdefault('forks', job_template.forks)
data.setdefault('limit', job_template.limit)
data.setdefault('verbosity', job_template.verbosity)
@@ -932,6 +963,7 @@ class JobSerializer(BaseSerializer):
data.setdefault('job_tags', job_template.job_tags)
return super(JobSerializer, self).from_native(data, files)
class JobHostSummarySerializer(BaseSerializer):
class Meta:
@@ -961,6 +993,7 @@ class JobHostSummarySerializer(BaseSerializer):
pass
return d
class JobEventSerializer(BaseSerializer):
event_display = serializers.Field(source='get_event_display2')
@@ -1055,7 +1088,6 @@ class ActivityStreamSerializer(BaseSerializer):
pass
return d
class AuthTokenSerializer(serializers.Serializer):
username = serializers.CharField()