diff --git a/awx/api/serializers.py b/awx/api/serializers.py index 05dca74cb6..66ca32764a 100644 --- a/awx/api/serializers.py +++ b/awx/api/serializers.py @@ -251,6 +251,7 @@ class BaseSerializer(serializers.ModelSerializer): 'inventory_update': _('Inventory Sync'), 'system_job': _('Management Job'), 'workflow_job': _('Workflow Job'), + 'workflow_job_template': _('Workflow Template'), } choices = [] for t in self.get_types(): diff --git a/awx/api/views.py b/awx/api/views.py index 48892e7f00..7d0586b296 100644 --- a/awx/api/views.py +++ b/awx/api/views.py @@ -1553,12 +1553,14 @@ class InventoryScriptList(ListCreateAPIView): model = CustomInventoryScript serializer_class = CustomInventoryScriptSerializer + new_in_210 = True class InventoryScriptDetail(RetrieveUpdateDestroyAPIView): model = CustomInventoryScript serializer_class = CustomInventoryScriptSerializer + new_in_210 = True def destroy(self, request, *args, **kwargs): instance = self.get_object() diff --git a/awx/main/management/commands/cleanup_facts.py b/awx/main/management/commands/cleanup_facts.py index a709f81c1a..f6b3c76b26 100644 --- a/awx/main/management/commands/cleanup_facts.py +++ b/awx/main/management/commands/cleanup_facts.py @@ -96,12 +96,12 @@ class Command(BaseCommand): option_list = BaseCommand.option_list + ( make_option('--older_than', dest='older_than', - default=None, - help='Specify the relative time to consider facts older than (w)eek (d)ay or (y)ear (i.e. 5d, 2w, 1y).'), + default='30d', + help='Specify the relative time to consider facts older than (w)eek (d)ay or (y)ear (i.e. 5d, 2w, 1y). Defaults to 30d.'), make_option('--granularity', dest='granularity', - default=None, - help='Window duration to group same hosts by for deletion (w)eek (d)ay or (y)ear (i.e. 5d, 2w, 1y).'), + default='1w', + help='Window duration to group same hosts by for deletion (w)eek (d)ay or (y)ear (i.e. 5d, 2w, 1y). Defaults to 1w.'), make_option('--module', dest='module', default=None, diff --git a/awx/main/management/commands/inventory_import.py b/awx/main/management/commands/inventory_import.py index 5c8c9df9c4..c1399e1a11 100644 --- a/awx/main/management/commands/inventory_import.py +++ b/awx/main/management/commands/inventory_import.py @@ -64,7 +64,7 @@ class MemObject(object): all_vars = {} files_found = 0 for suffix in ('', '.yml', '.yaml', '.json'): - path = ''.join([base_path, suffix]) + path = ''.join([base_path, suffix]).encode("utf-8") if not os.path.exists(path): continue if not os.path.isfile(path): @@ -462,7 +462,7 @@ class ExecutableJsonLoader(BaseLoader): # to set their variables for k,v in self.all_group.all_hosts.iteritems(): if 'hostvars' not in _meta: - data = self.command_to_json([self.source, '--host', k]) + data = self.command_to_json([self.source, '--host', k.encode("utf-8")]) else: data = _meta['hostvars'].get(k, {}) if isinstance(data, dict): diff --git a/awx/ui/client/legacy-styles/forms.less b/awx/ui/client/legacy-styles/forms.less index 89ff33dd03..570a096c7e 100644 --- a/awx/ui/client/legacy-styles/forms.less +++ b/awx/ui/client/legacy-styles/forms.less @@ -44,11 +44,10 @@ color: @list-header-txt; font-size: 14px; font-weight: bold; - padding-bottom: 25px; - min-height: 45px; word-break: break-all; max-width: 90%; word-wrap: break-word; + margin-bottom: 20px; } .Form-secondaryTitle{ diff --git a/awx/ui/client/src/access/add-rbac-resource/rbac-resource.partial.html b/awx/ui/client/src/access/add-rbac-resource/rbac-resource.partial.html index 75eaeb8302..f138e108d0 100644 --- a/awx/ui/client/src/access/add-rbac-resource/rbac-resource.partial.html +++ b/awx/ui/client/src/access/add-rbac-resource/rbac-resource.partial.html @@ -6,7 +6,7 @@
- {{ object.name }} + {{ object.name || object.username }}
Add Permissions
diff --git a/awx/ui/client/src/access/add-rbac-user-team/rbac-selected-list.directive.js b/awx/ui/client/src/access/add-rbac-user-team/rbac-selected-list.directive.js index f65d0324ad..7a66606e5f 100644 --- a/awx/ui/client/src/access/add-rbac-user-team/rbac-selected-list.directive.js +++ b/awx/ui/client/src/access/add-rbac-user-team/rbac-selected-list.directive.js @@ -42,8 +42,6 @@ export default ['$compile','templateUrl', 'i18n', 'generateList', list.listTitleBadge = false; - // @issue - fix field.columnClass values for this view - switch(scope.resourceType){ case 'projects': @@ -51,6 +49,8 @@ export default ['$compile','templateUrl', 'i18n', 'generateList', name: list.fields.name, scm_type: list.fields.scm_type }; + list.fields.name.columnClass = 'col-md-5 col-sm-5 col-xs-10'; + list.fields.scm_type.columnClass = 'col-md-5 col-sm-5 hidden-xs'; break; case 'inventories': @@ -58,6 +58,8 @@ export default ['$compile','templateUrl', 'i18n', 'generateList', name: list.fields.name, organization: list.fields.organization }; + list.fields.name.columnClass = 'col-md-5 col-sm-5 col-xs-10'; + list.fields.organization.columnClass = 'col-md-5 col-sm-5 hidden-xs'; break; case 'job_templates': @@ -67,6 +69,8 @@ export default ['$compile','templateUrl', 'i18n', 'generateList', name: list.fields.name, description: list.fields.description }; + list.fields.name.columnClass = 'col-md-5 col-sm-5 col-xs-10'; + list.fields.description.columnClass = 'col-md-5 col-sm-5 hidden-xs'; break; case 'workflow_templates': @@ -77,12 +81,16 @@ export default ['$compile','templateUrl', 'i18n', 'generateList', name: list.fields.name, description: list.fields.description }; + list.fields.name.columnClass = 'col-md-5 col-sm-5 col-xs-10'; + list.fields.description.columnClass = 'col-md-5 col-sm-5 hidden-xs'; break; case 'credentials': list.fields = { name: list.fields.name, description: list.fields.description }; + list.fields.name.columnClass = 'col-md-5 col-sm-5 col-xs-10'; + list.fields.description.columnClass = 'col-md-5 col-sm-5 hidden-xs'; } list.fields = _.each(list.fields, (field) => field.nosort = true); diff --git a/awx/ui/client/src/access/add-rbac-user-team/rbac-user-team.partial.html b/awx/ui/client/src/access/add-rbac-user-team/rbac-user-team.partial.html index 975870944c..a89621eda8 100644 --- a/awx/ui/client/src/access/add-rbac-user-team/rbac-user-team.partial.html +++ b/awx/ui/client/src/access/add-rbac-user-team/rbac-user-team.partial.html @@ -7,7 +7,7 @@
- {{ owner.name }} + {{ owner.name || owner.username }}
Add Permissions
diff --git a/awx/ui/client/src/access/add-rbac.block.less b/awx/ui/client/src/access/add-rbac.block.less index 88f5b1211f..0bc6617ba4 100644 --- a/awx/ui/client/src/access/add-rbac.block.less +++ b/awx/ui/client/src/access/add-rbac.block.less @@ -51,6 +51,10 @@ padding-top: 20px; } +.AddPermissions-list { + margin-bottom: 20px; +} + .AddPermissions-list .List-searchRow { height: 0px; } diff --git a/awx/ui/client/src/access/rbac-multiselect/permissionsUsers.list.js b/awx/ui/client/src/access/rbac-multiselect/permissionsUsers.list.js index 8955d30aa0..58a5605281 100644 --- a/awx/ui/client/src/access/rbac-multiselect/permissionsUsers.list.js +++ b/awx/ui/client/src/access/rbac-multiselect/permissionsUsers.list.js @@ -34,7 +34,7 @@ username: { key: true, label: 'Username', - columnClass: 'col-md-3 col-sm-3 col-xs-9' + columnClass: 'col-md-5 col-sm-5 col-xs-11' }, }, diff --git a/awx/ui/client/src/access/rbac-multiselect/rbac-multiselect-list.directive.js b/awx/ui/client/src/access/rbac-multiselect/rbac-multiselect-list.directive.js index da80fa4a58..0e277c3f5f 100644 --- a/awx/ui/client/src/access/rbac-multiselect/rbac-multiselect-list.directive.js +++ b/awx/ui/client/src/access/rbac-multiselect/rbac-multiselect-list.directive.js @@ -43,6 +43,8 @@ export default ['addPermissionsTeamsList', 'addPermissionsUsersList', 'TemplateL name: list.fields.name, scm_type: list.fields.scm_type }; + list.fields.name.columnClass = 'col-md-6 col-sm-6 col-xs-11'; + list.fields.scm_type.columnClass = 'col-md-5 col-sm-5 hidden-xs'; break; case 'Inventories': @@ -50,6 +52,8 @@ export default ['addPermissionsTeamsList', 'addPermissionsUsersList', 'TemplateL name: list.fields.name, organization: list.fields.organization }; + list.fields.name.columnClass = 'col-md-6 col-sm-6 col-xs-11'; + list.fields.organization.columnClass = 'col-md-5 col-sm-5 hidden-xs'; break; case 'JobTemplates': @@ -59,6 +63,8 @@ export default ['addPermissionsTeamsList', 'addPermissionsUsersList', 'TemplateL name: list.fields.name, description: list.fields.description }; + list.fields.name.columnClass = 'col-md-6 col-sm-6 col-xs-11'; + list.fields.description.columnClass = 'col-md-5 col-sm-5 hidden-xs'; break; case 'WorkflowTemplates': @@ -69,6 +75,8 @@ export default ['addPermissionsTeamsList', 'addPermissionsUsersList', 'TemplateL name: list.fields.name, description: list.fields.description }; + list.fields.name.columnClass = 'col-md-6 col-sm-6 col-xs-11'; + list.fields.description.columnClass = 'col-md-5 col-sm-5 hidden-xs'; break; case 'Users': list.fields = { @@ -76,12 +84,17 @@ export default ['addPermissionsTeamsList', 'addPermissionsUsersList', 'TemplateL first_name: list.fields.first_name, last_name: list.fields.last_name }; + list.fields.username.columnClass = 'col-md-5 col-sm-5 col-xs-11'; + list.fields.first_name.columnClass = 'col-md-3 col-sm-3 hidden-xs'; + list.fields.last_name.columnClass = 'col-md-3 col-sm-3 hidden-xs'; break; default: list.fields = { name: list.fields.name, description: list.fields.description }; + list.fields.name.columnClass = 'col-md-6 col-sm-6 col-xs-11'; + list.fields.description.columnClass = 'col-md-5 col-sm-5 hidden-xs'; } list_html = generateList.build({ diff --git a/awx/ui/client/src/activity-stream/streamDetailModal/streamDetailModal.block.less b/awx/ui/client/src/activity-stream/streamDetailModal/streamDetailModal.block.less index 6b00dc76f5..9e0cc73720 100644 --- a/awx/ui/client/src/activity-stream/streamDetailModal/streamDetailModal.block.less +++ b/awx/ui/client/src/activity-stream/streamDetailModal/streamDetailModal.block.less @@ -35,5 +35,6 @@ margin-bottom: 0; max-height: 200px; overflow: scroll; + overflow-x: auto; color: @as-detail-changes-txt; } diff --git a/awx/ui/client/src/activity-stream/streamDetailModal/streamDetailModal.partial.html b/awx/ui/client/src/activity-stream/streamDetailModal/streamDetailModal.partial.html index f5d5acf553..67e4452ebc 100644 --- a/awx/ui/client/src/activity-stream/streamDetailModal/streamDetailModal.partial.html +++ b/awx/ui/client/src/activity-stream/streamDetailModal/streamDetailModal.partial.html @@ -22,7 +22,7 @@
diff --git a/awx/ui/client/src/configuration/auth-form/sub-forms/auth-azure.form.js b/awx/ui/client/src/configuration/auth-form/sub-forms/auth-azure.form.js index 17b36e67fb..bb5bbef1a1 100644 --- a/awx/ui/client/src/configuration/auth-form/sub-forms/auth-azure.form.js +++ b/awx/ui/client/src/configuration/auth-form/sub-forms/auth-azure.form.js @@ -16,7 +16,8 @@ reset: 'SOCIAL_AUTH_AZUREAD_OAUTH2_KEY' }, SOCIAL_AUTH_AZUREAD_OAUTH2_SECRET: { - type: 'text', + type: 'sensitive', + hasShowInputButton: true, reset: 'SOCIAL_AUTH_AZUREAD_OAUTH2_SECRET' }, SOCIAL_AUTH_AZUREAD_OAUTH2_ORGANIZATION_MAP: { @@ -38,8 +39,8 @@ buttons: { reset: { ngClick: 'vm.resetAllConfirm()', - label: i18n._('Reset All'), - class: 'Form-button--left Form-cancelButton' + label: i18n._('Revert all to default'), + class: 'Form-resetAll' }, cancel: { ngClick: 'vm.formCancel()', diff --git a/awx/ui/client/src/configuration/auth-form/sub-forms/auth-github-org.form.js b/awx/ui/client/src/configuration/auth-form/sub-forms/auth-github-org.form.js index bd547cf8b1..9aecc2699f 100644 --- a/awx/ui/client/src/configuration/auth-form/sub-forms/auth-github-org.form.js +++ b/awx/ui/client/src/configuration/auth-form/sub-forms/auth-github-org.form.js @@ -16,7 +16,8 @@ export default ['i18n', function(i18n) { reset: 'SOCIAL_AUTH_GITHUB_ORG_KEY' }, SOCIAL_AUTH_GITHUB_ORG_SECRET: { - type: 'text', + type: 'sensitive', + hasShowInputButton: true, reset: 'SOCIAL_AUTH_GITHUB_ORG_SECRET' }, SOCIAL_AUTH_GITHUB_ORG_NAME: { @@ -28,8 +29,8 @@ export default ['i18n', function(i18n) { buttons: { reset: { ngClick: 'vm.resetAllConfirm()', - label: i18n._('Reset All'), - class: 'Form-button--left Form-cancelButton' + label: i18n._('Revert all to default'), + class: 'Form-resetAll' }, cancel: { ngClick: 'vm.formCancel()', diff --git a/awx/ui/client/src/configuration/auth-form/sub-forms/auth-github-team.form.js b/awx/ui/client/src/configuration/auth-form/sub-forms/auth-github-team.form.js index d43d8c01be..3747127132 100644 --- a/awx/ui/client/src/configuration/auth-form/sub-forms/auth-github-team.form.js +++ b/awx/ui/client/src/configuration/auth-form/sub-forms/auth-github-team.form.js @@ -16,7 +16,8 @@ export default ['i18n', function(i18n) { reset: 'SOCIAL_AUTH_GITHUB_TEAM_KEY' }, SOCIAL_AUTH_GITHUB_TEAM_SECRET: { - type: 'text', + type: 'sensitive', + hasShowInputButton: true, reset: 'SOCIAL_AUTH_GITHUB_TEAM_SECRET' }, SOCIAL_AUTH_GITHUB_TEAM_ID: { @@ -28,8 +29,8 @@ export default ['i18n', function(i18n) { buttons: { reset: { ngClick: 'vm.resetAllConfirm()', - label: i18n._('Reset All'), - class: 'Form-button--left Form-cancelButton' + label: i18n._('Revert all to default'), + class: 'Form-resetAll' }, cancel: { ngClick: 'vm.formCancel()', diff --git a/awx/ui/client/src/configuration/auth-form/sub-forms/auth-github.form.js b/awx/ui/client/src/configuration/auth-form/sub-forms/auth-github.form.js index 03af137a7c..f8af9ea74d 100644 --- a/awx/ui/client/src/configuration/auth-form/sub-forms/auth-github.form.js +++ b/awx/ui/client/src/configuration/auth-form/sub-forms/auth-github.form.js @@ -16,7 +16,8 @@ export default ['i18n', function(i18n) { reset: 'SOCIAL_AUTH_GITHUB_KEY' }, SOCIAL_AUTH_GITHUB_SECRET: { - type: 'text', + type: 'sensitive', + hasShowInputButton: true, reset: 'SOCIAL_AUTH_GITHUB_SECRET' } }, @@ -24,8 +25,8 @@ export default ['i18n', function(i18n) { buttons: { reset: { ngClick: 'vm.resetAllConfirm()', - label: i18n._('Reset All'), - class: 'Form-button--left Form-cancelButton' + label: i18n._('Revert all to default'), + class: 'Form-resetAll' }, cancel: { ngClick: 'vm.formCancel()', diff --git a/awx/ui/client/src/configuration/auth-form/sub-forms/auth-google-oauth2.form.js b/awx/ui/client/src/configuration/auth-form/sub-forms/auth-google-oauth2.form.js index ac1c23545e..8842570974 100644 --- a/awx/ui/client/src/configuration/auth-form/sub-forms/auth-google-oauth2.form.js +++ b/awx/ui/client/src/configuration/auth-form/sub-forms/auth-google-oauth2.form.js @@ -16,7 +16,8 @@ export default ['i18n', function(i18n) { reset: 'SOCIAL_AUTH_GOOGLE_OAUTH2_KEY' }, SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET: { - type: 'text', + type: 'sensitive', + hasShowInputButton: true, reset: 'SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET' }, SOCIAL_AUTH_GOOGLE_OAUTH2_WHITELISTED_DOMAINS: { @@ -36,8 +37,8 @@ export default ['i18n', function(i18n) { buttons: { reset: { ngClick: 'vm.resetAllConfirm()', - label: i18n._('Reset All'), - class: 'Form-button--left Form-cancelButton' + label: i18n._('Revert all to default'), + class: 'Form-resetAll' }, cancel: { ngClick: 'vm.formCancel()', diff --git a/awx/ui/client/src/configuration/auth-form/sub-forms/auth-ldap.form.js b/awx/ui/client/src/configuration/auth-form/sub-forms/auth-ldap.form.js index 8d38fea688..0943d21b27 100644 --- a/awx/ui/client/src/configuration/auth-form/sub-forms/auth-ldap.form.js +++ b/awx/ui/client/src/configuration/auth-form/sub-forms/auth-ldap.form.js @@ -21,7 +21,8 @@ export default ['i18n', function(i18n) { reset: 'AUTH_LDAP_BIND_DN' }, AUTH_LDAP_BIND_PASSWORD: { - type: 'password' + type: 'sensitive', + hasShowInputButton: true, }, AUTH_LDAP_USER_SEARCH: { type: 'textarea', @@ -84,8 +85,8 @@ export default ['i18n', function(i18n) { buttons: { reset: { ngClick: 'vm.resetAllConfirm()', - label: i18n._('Reset All'), - class: 'Form-button--left Form-cancelButton' + label: i18n._('Revert all to default'), + class: 'Form-resetAll' }, cancel: { ngClick: 'vm.formCancel()', diff --git a/awx/ui/client/src/configuration/auth-form/sub-forms/auth-radius.form.js b/awx/ui/client/src/configuration/auth-form/sub-forms/auth-radius.form.js index b16fd649dc..f8aa37b014 100644 --- a/awx/ui/client/src/configuration/auth-form/sub-forms/auth-radius.form.js +++ b/awx/ui/client/src/configuration/auth-form/sub-forms/auth-radius.form.js @@ -21,7 +21,8 @@ export default ['i18n', function(i18n) { reset: 'RADIUS_PORT' }, RADIUS_SECRET: { - type: 'text', + type: 'sensitive', + hasShowInputButton: true, reset: 'RADIUS_SECRET' } }, @@ -29,8 +30,8 @@ export default ['i18n', function(i18n) { buttons: { reset: { ngClick: 'vm.resetAllConfirm()', - label: i18n._('Reset All'), - class: 'Form-button--left Form-cancelButton' + label: i18n._('Revert all to default'), + class: 'Form-resetAll' }, cancel: { ngClick: 'vm.formCancel()', diff --git a/awx/ui/client/src/configuration/auth-form/sub-forms/auth-saml.form.js b/awx/ui/client/src/configuration/auth-form/sub-forms/auth-saml.form.js index ca2bb50dcb..698bcbc6bd 100644 --- a/awx/ui/client/src/configuration/auth-form/sub-forms/auth-saml.form.js +++ b/awx/ui/client/src/configuration/auth-form/sub-forms/auth-saml.form.js @@ -20,7 +20,8 @@ export default ['i18n', function(i18n) { reset: 'SOCIAL_AUTH_SAML_SP_PUBLIC_CERT' }, SOCIAL_AUTH_SAML_SP_PRIVATE_KEY: { - type: 'text', + type: 'sensitive', + hasShowInputButton: true, reset: 'SOCIAL_AUTH_SAML_SP_PRIVATE_KEY' }, SOCIAL_AUTH_SAML_ORG_INFO: { @@ -56,8 +57,8 @@ export default ['i18n', function(i18n) { buttons: { reset: { ngClick: 'vm.resetAllConfirm()', - label: i18n._('Reset All'), - class: 'Form-button--left Form-cancelButton' + label: i18n._('Revert all to default'), + class: 'Form-resetAll' }, cancel: { ngClick: 'vm.formCancel()', diff --git a/awx/ui/client/src/configuration/configuration.block.less b/awx/ui/client/src/configuration/configuration.block.less index 0b2a1ea0ee..b25d36e400 100644 --- a/awx/ui/client/src/configuration/configuration.block.less +++ b/awx/ui/client/src/configuration/configuration.block.less @@ -12,6 +12,19 @@ float: right } +.Form-resetAll { + border: none; + padding: 0; + background-color: @white; + margin-right: auto; + color: @default-link; + font-size: 12px; + + &:hover { + color: @default-link-hov; + } +} + .Form-tab { min-width: 77px; } diff --git a/awx/ui/client/src/configuration/jobs-form/configuration-jobs.form.js b/awx/ui/client/src/configuration/jobs-form/configuration-jobs.form.js index caf0392c24..99e52498c2 100644 --- a/awx/ui/client/src/configuration/jobs-form/configuration-jobs.form.js +++ b/awx/ui/client/src/configuration/jobs-form/configuration-jobs.form.js @@ -64,8 +64,8 @@ buttons: { reset: { ngClick: 'vm.resetAllConfirm()', - label: i18n._('Reset All'), - class: 'Form-button--left Form-cancelButton' + label: i18n._('Revert all to default'), + class: 'Form-resetAll' }, cancel: { ngClick: 'vm.formCancel()', diff --git a/awx/ui/client/src/configuration/system-form/sub-forms/system-activity-stream.form.js b/awx/ui/client/src/configuration/system-form/sub-forms/system-activity-stream.form.js index 09cf80eccd..3dc7fd89f7 100644 --- a/awx/ui/client/src/configuration/system-form/sub-forms/system-activity-stream.form.js +++ b/awx/ui/client/src/configuration/system-form/sub-forms/system-activity-stream.form.js @@ -22,8 +22,8 @@ buttons: { reset: { ngClick: 'vm.resetAllConfirm()', - label: i18n._('Reset All'), - class: 'Form-button--left Form-cancelButton' + label: i18n._('Revert all to default'), + class: 'Form-resetAll' }, cancel: { ngClick: 'vm.formCancel()', diff --git a/awx/ui/client/src/configuration/system-form/sub-forms/system-logging.form.js b/awx/ui/client/src/configuration/system-form/sub-forms/system-logging.form.js index ee99024b45..f2ed9f54e3 100644 --- a/awx/ui/client/src/configuration/system-form/sub-forms/system-logging.form.js +++ b/awx/ui/client/src/configuration/system-form/sub-forms/system-logging.form.js @@ -30,7 +30,8 @@ reset: 'LOG_AGGREGATOR_USERNAME' }, LOG_AGGREGATOR_PASSWORD: { - type: 'text', + type: 'sensitive', + hasShowInputButton: true, reset: 'LOG_AGGREGATOR_PASSWORD' }, LOG_AGGREGATOR_LOGGERS: { @@ -48,8 +49,8 @@ buttons: { reset: { ngClick: 'vm.resetAllConfirm()', - label: i18n._('Reset All'), - class: 'Form-button--left Form-cancelButton' + label: i18n._('Revert all to default'), + class: 'Form-resetAll' }, cancel: { ngClick: 'vm.formCancel()', diff --git a/awx/ui/client/src/configuration/system-form/sub-forms/system-misc.form.js b/awx/ui/client/src/configuration/system-form/sub-forms/system-misc.form.js index 690418f323..892dfd0bc0 100644 --- a/awx/ui/client/src/configuration/system-form/sub-forms/system-misc.form.js +++ b/awx/ui/client/src/configuration/system-form/sub-forms/system-misc.form.js @@ -26,8 +26,8 @@ export default ['i18n', function(i18n) { buttons: { reset: { ngClick: 'vm.resetAllConfirm()', - label: i18n._('Reset All'), - class: 'Form-button--left Form-cancelButton' + label: i18n._('Revert all to default'), + class: 'Form-resetAll' }, cancel: { ngClick: 'vm.formCancel()', diff --git a/awx/ui/client/src/configuration/ui-form/configuration-ui.form.js b/awx/ui/client/src/configuration/ui-form/configuration-ui.form.js index 0ef2cb44ff..e566c076d1 100644 --- a/awx/ui/client/src/configuration/ui-form/configuration-ui.form.js +++ b/awx/ui/client/src/configuration/ui-form/configuration-ui.form.js @@ -32,8 +32,8 @@ export default ['i18n', function(i18n) { buttons: { reset: { ngClick: 'vm.resetAllConfirm()', - label: i18n._('Reset All'), - class: 'Form-button--left Form-cancelButton' + label: i18n._('Revert all to default'), + class: 'Form-resetAll' }, cancel: { ngClick: 'vm.formCancel()', diff --git a/awx/ui/client/src/controllers/Credentials.js b/awx/ui/client/src/controllers/Credentials.js index a64056ccd4..2bddc26f0d 100644 --- a/awx/ui/client/src/controllers/Credentials.js +++ b/awx/ui/client/src/controllers/Credentials.js @@ -283,7 +283,7 @@ CredentialsAdd.$inject = ['$scope', '$rootScope', '$compile', '$location', export function CredentialsEdit($scope, $rootScope, $compile, $location, $log, $stateParams, CredentialForm, Rest, Alert, ProcessErrors, ClearScope, Prompt, GetBasePath, GetChoices, KindChange, Empty, OwnerChange, FormSave, Wait, - $state, CreateSelect2, Authorization) { + $state, CreateSelect2, Authorization, i18n) { ClearScope(); @@ -336,13 +336,14 @@ export function CredentialsEdit($scope, $rootScope, $compile, $location, $log, }); } - // if the credential is assigned to an organization, allow permission delegation - // do NOT use $scope.organization in a view directive to determine if a credential is associated with an org - // @todo why not? ^ and what is this type check for a number doing - should this be a type check for undefined? - $scope.disablePermissionAssignment = typeof($scope.organization) === 'number' ? false : true; - if ($scope.disablePermissionAssignment) { - $scope.permissionsTooltip = 'Credentials are only shared within an organization. Assign credentials to an organization to delegate credential permissions. The organization cannot be edited after credentials are assigned.'; - } + $scope.$watch('organization', function(val) { + if (val === undefined) { + $scope.permissionsTooltip = i18n._('Credentials are only shared within an organization. Assign credentials to an organization to delegate credential permissions. The organization cannot be edited after credentials are assigned.'); + } else { + $scope.permissionsTooltip = ''; + } + }); + setAskCheckboxes(); KindChange({ scope: $scope, @@ -613,5 +614,5 @@ CredentialsEdit.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log', '$stateParams', 'CredentialForm', 'Rest', 'Alert', 'ProcessErrors', 'ClearScope', 'Prompt', 'GetBasePath', 'GetChoices', 'KindChange', 'Empty', 'OwnerChange', - 'FormSave', 'Wait', '$state', 'CreateSelect2', 'Authorization' + 'FormSave', 'Wait', '$state', 'CreateSelect2', 'Authorization', 'i18n', ]; diff --git a/awx/ui/client/src/dashboard/lists/dashboard-list.block.less b/awx/ui/client/src/dashboard/lists/dashboard-list.block.less index 102188034d..0903b01c74 100644 --- a/awx/ui/client/src/dashboard/lists/dashboard-list.block.less +++ b/awx/ui/client/src/dashboard/lists/dashboard-list.block.less @@ -32,34 +32,21 @@ } .DashboardList-viewAll { - color: @btn-txt; - background-color: @btn-bg; - font-size: 12px; - border: 1px solid @default-icon-hov; - border-radius: 5px; + font-size: 11px; margin-right: 15px; - margin-top: 10px; + margin-top: 13px; margin-bottom: 10px; padding-left: 10px; padding-right: 10px; padding-bottom: 5px; padding-top: 5px; - transition: background-color 0.2s; -} - -.DashboardList-viewAll:hover { - color: @btn-txt; - background-color: @btn-bg-hov; -} - -.DashboardList-viewAll:focus { - color: @btn-txt; } .DashboardList-container { flex: 1; width: 100%; padding: 20px; + padding-top: 0; } .DashboardList-tableHeader--name { diff --git a/awx/ui/client/src/forms/Credentials.js b/awx/ui/client/src/forms/Credentials.js index 9d816c9ce4..727172c94c 100644 --- a/awx/ui/client/src/forms/Credentials.js +++ b/awx/ui/client/src/forms/Credentials.js @@ -420,7 +420,9 @@ export default related: { permissions: { - disabled: 'disablePermissionAssignment', + disabled: '(organization === undefined ? true : false)', + // Do not transition the state if organization is undefined + ngClick: `(organization === undefined ? true : false)||$state.go('credentials.edit.permissions')`, awToolTip: '{{permissionsTooltip}}', dataTipWatch: 'permissionsTooltip', dataPlacement: 'top', diff --git a/awx/ui/client/src/forms/Groups.js b/awx/ui/client/src/forms/Groups.js index 944fddd2c5..c5bf595ca2 100644 --- a/awx/ui/client/src/forms/Groups.js +++ b/awx/ui/client/src/forms/Groups.js @@ -43,7 +43,7 @@ export default label: 'Variables', type: 'textarea', class: 'Form-textAreaLabel Form-formGroup--fullWidth', - rows: 12, + rows: 6, 'default': '---', dataTitle: 'Group Variables', dataPlacement: 'right', diff --git a/awx/ui/client/src/forms/Inventories.js b/awx/ui/client/src/forms/Inventories.js index e7106b8277..b78e16064d 100644 --- a/awx/ui/client/src/forms/Inventories.js +++ b/awx/ui/client/src/forms/Inventories.js @@ -78,7 +78,7 @@ angular.module('InventoryFormDefinition', ['ScanJobsListDefinition']) }, close: { ngClick: 'formCancel()', - ngHide: '(inventory_obj.summary_fields.user_capabilities.edit || canAdd)' + ngShow: '!(inventory_obj.summary_fields.user_capabilities.edit || canAdd)' }, save: { ngClick: 'formSave()', diff --git a/awx/ui/client/src/helpers/Jobs.js b/awx/ui/client/src/helpers/Jobs.js index 9f64ac8906..d7649d1c33 100644 --- a/awx/ui/client/src/helpers/Jobs.js +++ b/awx/ui/client/src/helpers/Jobs.js @@ -233,7 +233,7 @@ export default hdr: hdr, body: (action_label === 'cancel' || job.status === 'new') ? cancelBody : deleteBody, action: action, - actionText: (action_label === 'cancel' || job.status === 'new') ? "YES" : "DELETE" + actionText: (action_label === 'cancel' || job.status === 'new') ? "OK" : "DELETE" }); }); diff --git a/awx/ui/client/src/inventories/add/inventory-add.controller.js b/awx/ui/client/src/inventories/add/inventory-add.controller.js index 7f08e716a6..e6f9b7e3a3 100644 --- a/awx/ui/client/src/inventories/add/inventory-add.controller.js +++ b/awx/ui/client/src/inventories/add/inventory-add.controller.js @@ -11,10 +11,16 @@ */ function InventoriesAdd($scope, $rootScope, $compile, $location, $log, - $stateParams, GenerateForm, InventoryForm, Rest, Alert, ProcessErrors, + $stateParams, GenerateForm, InventoryForm, rbacUiControlService, Rest, Alert, ProcessErrors, ClearScope, GetBasePath, ParseTypeChange, Wait, ToJSON, $state) { + $scope.canAdd = false; + rbacUiControlService.canAdd(GetBasePath('inventory')) + .then(function(canAdd) { + $scope.canAdd = canAdd; + }); + Rest.setUrl(GetBasePath('inventory')); Rest.options() .success(function(data) { @@ -91,7 +97,7 @@ function InventoriesAdd($scope, $rootScope, $compile, $location, $log, } export default ['$scope', '$rootScope', '$compile', '$location', - '$log', '$stateParams', 'GenerateForm', 'InventoryForm', 'Rest', 'Alert', + '$log', '$stateParams', 'GenerateForm', 'InventoryForm', 'rbacUiControlService', 'Rest', 'Alert', 'ProcessErrors', 'ClearScope', 'GetBasePath', 'ParseTypeChange', 'Wait', 'ToJSON', '$state', InventoriesAdd ]; diff --git a/awx/ui/client/src/inventories/edit/inventory-edit.controller.js b/awx/ui/client/src/inventories/edit/inventory-edit.controller.js index ba6de0f183..3e26dec8dc 100644 --- a/awx/ui/client/src/inventories/edit/inventory-edit.controller.js +++ b/awx/ui/client/src/inventories/edit/inventory-edit.controller.js @@ -32,7 +32,7 @@ function InventoriesEdit($scope, $rootScope, $compile, $location, form.formFieldSize = null; $scope.inventory_id = inventory_id; - $scope.$watch('invnentory_obj.summary_fields.user_capabilities.edit', function(val) { + $scope.$watch('inventory_obj.summary_fields.user_capabilities.edit', function(val) { if (val === false) { $scope.canAdd = false; } diff --git a/awx/ui/client/src/inventories/main.js b/awx/ui/client/src/inventories/main.js index 8505c9b80f..ac031283cd 100644 --- a/awx/ui/client/src/inventories/main.js +++ b/awx/ui/client/src/inventories/main.js @@ -66,7 +66,19 @@ angular.module('inventory', [ ], ParentObject: ['groupData', function(groupData) { return groupData; - }] + }], + UnifiedJobsOptions: ['Rest', 'GetBasePath', '$stateParams', '$q', + function(Rest, GetBasePath, $stateParams, $q) { + Rest.setUrl(GetBasePath('unified_jobs')); + var val = $q.defer(); + Rest.options() + .then(function(data) { + val.resolve(data.data); + }, function(data) { + val.reject(data); + }); + return val.promise; + }] }, views: { // clear form template when views render in this substate diff --git a/awx/ui/client/src/inventories/manage/groups/groups-edit.controller.js b/awx/ui/client/src/inventories/manage/groups/groups-edit.controller.js index 1b54bc92f1..ae90cae8bf 100644 --- a/awx/ui/client/src/inventories/manage/groups/groups-edit.controller.js +++ b/awx/ui/client/src/inventories/manage/groups/groups-edit.controller.js @@ -123,7 +123,7 @@ export default ['$state', '$stateParams', '$scope', 'ToggleNotification', 'Parse $scope.source = source; if (source.value === 'ec2' || source.value === 'custom' || source.value === 'vmware' || source.value === 'openstack') { - $scope[source.value + '_variables'] = $scope[source.value + '_variables'] === null ? '---' : $scope[source.value + '_variables']; + $scope[source.value + '_variables'] = $scope[source.value + '_variables'] === (null || undefined) ? '---' : $scope[source.value + '_variables']; ParseTypeChange({ scope: $scope, field_id: source.value + '_variables', diff --git a/awx/ui/client/src/lists/AllJobs.js b/awx/ui/client/src/lists/AllJobs.js index 12a94a5f1b..d5e73c3982 100644 --- a/awx/ui/client/src/lists/AllJobs.js +++ b/awx/ui/client/src/lists/AllJobs.js @@ -18,6 +18,7 @@ export default hover: true, well: false, emptyListText: i18n._('No jobs have yet run.'), + title: false, fields: { status: { diff --git a/awx/ui/client/src/lists/Projects.js b/awx/ui/client/src/lists/Projects.js index bf8fde2d03..34cf545035 100644 --- a/awx/ui/client/src/lists/Projects.js +++ b/awx/ui/client/src/lists/Projects.js @@ -42,14 +42,14 @@ export default scm_revision: { label: i18n._('Revision'), excludeModal: true, - columnClass: 'col-lg-3 col-md-2 col-sm-3 hidden-xs', + columnClass: 'col-lg-4 col-md-2 col-sm-3 hidden-xs', class: 'List-staticColumnAdjacent--monospace' }, scm_type: { label: i18n._('Type'), ngBind: 'project.type_label', excludeModal: true, - columnClass: 'col-lg-3 col-md-2 col-sm-3 hidden-xs' + columnClass: 'col-lg-2 col-md-2 col-sm-3 hidden-xs' }, last_updated: { label: i18n._('Last Updated'), @@ -61,6 +61,14 @@ export default }, actions: { + refresh: { + mode: 'all', + awToolTip: i18n._("Refresh the page"), + ngClick: "refresh()", + ngShow: "socketStatus === 'error'", + actionClass: 'btn List-buttonDefault', + buttonContent: i18n._('REFRESH') + }, add: { mode: 'all', // One of: edit, select, all ngClick: 'addProject()', @@ -68,14 +76,6 @@ export default actionClass: 'btn List-buttonSubmit', buttonContent: '+ ' + i18n._('ADD'), ngShow: "canAdd" - }, - refresh: { - mode: 'all', - awToolTip: i18n._("Refresh the page"), - ngClick: "refresh()", - ngShow: "socketStatus == 'error'", - actionClass: 'btn List-buttonDefault', - buttonContent: i18n._('REFRESH') } }, diff --git a/awx/ui/client/src/management-jobs/scheduler/schedulerForm.partial.html b/awx/ui/client/src/management-jobs/scheduler/schedulerForm.partial.html index b619ead47a..d68ebfe3b8 100644 --- a/awx/ui/client/src/management-jobs/scheduler/schedulerForm.partial.html +++ b/awx/ui/client/src/management-jobs/scheduler/schedulerForm.partial.html @@ -507,11 +507,15 @@
+ +
+ + +
Please enter the number of days you would like to keep this data.
Please enter a valid number.
Please enter a non-negative number.
Please enter a number smaller than 9999.
-
@@ -520,11 +524,15 @@
+ +
+ + +
Please enter the number of days you would like to keep this data.
Please enter a valid number.
Please enter a non-negative number.
Please enter a number smaller than 9999.
-
diff --git a/awx/ui/client/src/organizations/list/organizations-list.controller.js b/awx/ui/client/src/organizations/list/organizations-list.controller.js index 9bae54afc8..3849c123a4 100644 --- a/awx/ui/client/src/organizations/list/organizations-list.controller.js +++ b/awx/ui/client/src/organizations/list/organizations-list.controller.js @@ -127,6 +127,16 @@ export default ['$stateParams', '$scope', '$rootScope', '$location', }); }; + function isDeletedOrganizationBeingEdited(deleted_organization_id, editing_organization_id) { + if (editing_organization_id === undefined) { + return false; + } + if (deleted_organization_id === editing_organization_id) { + return true; + } + return false; + } + $scope.deleteOrganization = function(id, name) { var action = function() { @@ -137,7 +147,11 @@ export default ['$stateParams', '$scope', '$rootScope', '$location', Rest.destroy() .success(function() { Wait('stop'); - $state.reload('organizations'); + if (isDeletedOrganizationBeingEdited(id, parseInt($stateParams.organization_id)) === true) { + $state.go('^', null, { reload: true }); + } else { + $state.reload('organizations'); + } }) .error(function(data, status) { ProcessErrors($scope, data, status, null, { diff --git a/awx/ui/client/src/partials/jobs.html b/awx/ui/client/src/partials/jobs.html index 00de9af821..46f7b09761 100644 --- a/awx/ui/client/src/partials/jobs.html +++ b/awx/ui/client/src/partials/jobs.html @@ -16,7 +16,7 @@ -
+
diff --git a/awx/ui/client/src/shared/Utilities.js b/awx/ui/client/src/shared/Utilities.js index 9bc18dfd13..3bb9c02de0 100644 --- a/awx/ui/client/src/shared/Utilities.js +++ b/awx/ui/client/src/shared/Utilities.js @@ -198,6 +198,8 @@ angular.module('Utilities', ['RestServices', 'Utilities', 'sanitizeFilter']) msg += 'Please contact your system administrator.'; } Alert(defaultMsg.hdr, msg); + } else if (status === 409) { + Alert('Conflict', data.conflict || "Resource currently in use."); } else if (status === 410) { Alert('Deleted Object', 'The requested object was previously deleted and can no longer be accessed.'); } else if ((status === 'Token is expired') || (status === 401 && data.detail && data.detail === 'Token is expired') || diff --git a/awx/ui/client/src/shared/directives.js b/awx/ui/client/src/shared/directives.js index 1da55f80f8..55278c5ab9 100644 --- a/awx/ui/client/src/shared/directives.js +++ b/awx/ui/client/src/shared/directives.js @@ -620,12 +620,10 @@ angular.module('AWDirectives', ['RestServices', 'Utilities', 'JobsHelper']) if (attrs.tipWatch) { // Add dataTipWatch: 'variable_name' - scope.$watch(attrs.tipWatch, function(newVal, oldVal) { - if (newVal !== oldVal) { - // Where did fixTitle come from?: - // http://stackoverflow.com/questions/9501921/change-twitter-bootstrap-tooltip-content-on-click - $(element).tooltip('hide').attr('data-original-title', newVal).tooltip('fixTitle'); - } + scope.$watch(attrs.tipWatch, function(newVal) { + // Where did fixTitle come from?: + // http://stackoverflow.com/questions/9501921/change-twitter-bootstrap-tooltip-content-on-click + $(element).tooltip('hide').attr('data-original-title', newVal).tooltip('fixTitle'); }); } } diff --git a/awx/ui/client/src/shared/list-generator/list-generator.factory.js b/awx/ui/client/src/shared/list-generator/list-generator.factory.js index fd664dc167..36cb5e5a65 100644 --- a/awx/ui/client/src/shared/list-generator/list-generator.factory.js +++ b/awx/ui/client/src/shared/list-generator/list-generator.factory.js @@ -134,7 +134,7 @@ export default ['$location', '$compile', '$rootScope', 'Attr', 'Icon', base, action, fld, cnt, field_action, fAction, itm; if (options.mode !== 'lookup') { - if (options.title !== false) { + if (options.title !== false && list.title !== false) { html += "
"; html += "
"; @@ -311,7 +311,7 @@ export default ['$location', '$compile', '$rootScope', 'Attr', 'Icon', } if (list.multiSelect) { - innerTable += ''; + innerTable += ''; } // Change layout if a lookup list, place radio buttons before labels diff --git a/awx/ui/client/src/templates/list/templates-list.controller.js b/awx/ui/client/src/templates/list/templates-list.controller.js index 5bcd659a38..820f843852 100644 --- a/awx/ui/client/src/templates/list/templates-list.controller.js +++ b/awx/ui/client/src/templates/list/templates-list.controller.js @@ -131,7 +131,7 @@ export default ['$scope', '$rootScope', '$location', '$stateParams', 'Rest', handleSuccessfulDelete(); }, function (data) { Wait('stop'); - ProcessErrors($scope, data, status, null, { hdr: 'Error!', + ProcessErrors($scope, data, data.status, null, { hdr: 'Error!', msg: 'Call to delete workflow job template failed. DELETE returned status: ' + status }); }); } @@ -141,8 +141,8 @@ export default ['$scope', '$rootScope', '$location', '$stateParams', 'Rest', handleSuccessfulDelete(); }, function (data) { Wait('stop'); - ProcessErrors($scope, data, status, null, { hdr: 'Error!', - msg: 'Call to delete job template failed. DELETE returned status: ' + status }); + ProcessErrors($scope, data, data.status, null, { hdr: 'Error!', + msg: 'Call to delete job template failed. DELETE returned status: ' + data.status }); }); } else { diff --git a/awx/ui/templates/ui/index.html b/awx/ui/templates/ui/index.html index 9c8d91918f..3b29937bc0 100644 --- a/awx/ui/templates/ui/index.html +++ b/awx/ui/templates/ui/index.html @@ -81,7 +81,7 @@
diff --git a/docs/licenses/ntlm-auth-1.0.2.zip b/docs/licenses/ntlm-auth-1.0.2.zip new file mode 100644 index 0000000000..d847ae6be6 Binary files /dev/null and b/docs/licenses/ntlm-auth-1.0.2.zip differ diff --git a/docs/licenses/ntlm-auth.txt b/docs/licenses/ntlm-auth.txt new file mode 100644 index 0000000000..21429cb1fa --- /dev/null +++ b/docs/licenses/ntlm-auth.txt @@ -0,0 +1,163 @@ +GNU Lesser General Public License +================================= + +_Version 3, 29 June 2007_ +_Copyright © 2007 Free Software Foundation, Inc. <>_ + +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. + + +This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + +### 0. Additional Definitions + +As used herein, “this License” refers to version 3 of the GNU Lesser +General Public License, and the “GNU GPL” refers to version 3 of the GNU +General Public License. + +“The Library” refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + +An “Application” is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + +A “Combined Work” is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the “Linked +Version”. + +The “Minimal Corresponding Source” for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + +The “Corresponding Application Code” for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + +### 1. Exception to Section 3 of the GNU GPL + +You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + +### 2. Conveying Modified Versions + +If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + +* **a)** under this License, provided that you make a good faith effort to +ensure that, in the event an Application does not supply the +function or data, the facility still operates, and performs +whatever part of its purpose remains meaningful, or + +* **b)** under the GNU GPL, with none of the additional permissions of +this License applicable to that copy. + +### 3. Object Code Incorporating Material from Library Header Files + +The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + +* **a)** Give prominent notice with each copy of the object code that the +Library is used in it and that the Library and its use are +covered by this License. +* **b)** Accompany the object code with a copy of the GNU GPL and this license +document. + +### 4. Combined Works + +You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + +* **a)** Give prominent notice with each copy of the Combined Work that +the Library is used in it and that the Library and its use are +covered by this License. + +* **b)** Accompany the Combined Work with a copy of the GNU GPL and this license +document. + +* **c)** For a Combined Work that displays copyright notices during +execution, include the copyright notice for the Library among +these notices, as well as a reference directing the user to the +copies of the GNU GPL and this license document. + +* **d)** Do one of the following: + - **0)** Convey the Minimal Corresponding Source under the terms of this +License, and the Corresponding Application Code in a form +suitable for, and under terms that permit, the user to +recombine or relink the Application with a modified version of +the Linked Version to produce a modified Combined Work, in the +manner specified by section 6 of the GNU GPL for conveying +Corresponding Source. + - **1)** Use a suitable shared library mechanism for linking with the +Library. A suitable mechanism is one that **(a)** uses at run time +a copy of the Library already present on the user's computer +system, and **(b)** will operate properly with a modified version +of the Library that is interface-compatible with the Linked +Version. + +* **e)** Provide Installation Information, but only if you would otherwise +be required to provide such information under section 6 of the +GNU GPL, and only to the extent that such information is +necessary to install and execute a modified version of the +Combined Work produced by recombining or relinking the +Application with a modified version of the Linked Version. (If +you use option **4d0**, the Installation Information must accompany +the Minimal Corresponding Source and Corresponding Application +Code. If you use option **4d1**, you must provide the Installation +Information in the manner specified by section 6 of the GNU GPL +for conveying Corresponding Source.) + +### 5. Combined Libraries + +You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + +* **a)** Accompany the combined library with a copy of the same work based +on the Library, uncombined with any other library facilities, +conveyed under the terms of this License. +* **b)** Give prominent notice with the combined library that part of it +is a work based on the Library, and explaining where to find the +accompanying uncombined form of the same work. + +### 6. Revised Versions of the GNU Lesser General Public License + +The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License “or any later version” +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + +If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. \ No newline at end of file diff --git a/docs/licenses/pykerberos.txt b/docs/licenses/pykerberos.txt new file mode 100644 index 0000000000..d645695673 --- /dev/null +++ b/docs/licenses/pykerberos.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/docs/licenses/pywinrm.txt b/docs/licenses/pywinrm.txt index 3f28a5f534..3e21facc07 100644 --- a/docs/licenses/pywinrm.txt +++ b/docs/licenses/pywinrm.txt @@ -1,9 +1,19 @@ -MIT License +Copyright (c) 2013 Alexey Diyan -Copyright (c) +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/docs/licenses/requests-kerberos.txt b/docs/licenses/requests-kerberos.txt new file mode 100644 index 0000000000..581f115e78 --- /dev/null +++ b/docs/licenses/requests-kerberos.txt @@ -0,0 +1,15 @@ +ISC License + +Copyright (c) 2012 Kenneth Reitz + +Permission to use, copy, modify and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS-IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/docs/licenses/requests-ntlm.txt b/docs/licenses/requests-ntlm.txt new file mode 100644 index 0000000000..5f3e18de12 --- /dev/null +++ b/docs/licenses/requests-ntlm.txt @@ -0,0 +1,15 @@ +ISC License + +Copyright (c) 2013 Ben Toews + +Permission to use, copy, modify and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS-IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/docs/workflow.md b/docs/workflow.md index fcabb9891f..d7336bce08 100644 --- a/docs/workflow.md +++ b/docs/workflow.md @@ -32,7 +32,7 @@ As stated, workflow job templates can be created with populated `extra_vars`. Th Job resources spawned by workflow jobs are needed by workflow to run correctly. Therefore deletion of spawned job resources is blocked while the underlying workflow job is executing. -Other than success and failure, a workflow spawned job resource can also end with status 'error' and 'canceled'. When a workflow spawned job resource errors, all branches starting from that job will stop executing while the rest keep their own paces. Canceling a workflow spawned job resource follows the same rules. +Other than success and failure, a workflow spawned job resource can also end with status 'error' and 'canceled'. When a workflow spawned job resource errors, all branches starting from that job will stop executing while the rest continue executing. Canceling a workflow spawned job resource follows the same rules. If the unified job template of the node is null (which could be a result of deleting the unified job template or copying a workflow when the user lacks necessary permissions to use the resource), then the branch should stop executing in this case as well. A workflow job itself can also be canceled. In this case all its spawned job resources will be canceled if cancelable and following paths stop executing. @@ -47,11 +47,11 @@ Workflow job summary: ``` ### Workflow Copy and Relaunch -Other than the normal way of creating workflow job templates, it is also possible to copy existing workflow job templates. The resulting new workflow job template will be identical to which it copies from, except for `name` field which will be appended a text to indicate it's a copy. +Other than the normal way of creating workflow job templates, it is also possible to copy existing workflow job templates. The resulting new workflow job template will be mostly identical to the original, except for `name` field which will be appended a text to indicate it's a copy. -Workflow job templates can be copied by POSTing to endpoint `/workflow_job_templates/\d+/copy/`. After copy finished, the resulting new workflow job template will have identical fields including description, extra_vars, labels, 'launch_type' and survey-related fields (survey_passwords, survey_spec and survey_enabled). More importantly, workflow job template node of the original workflow job template, as well as the topology they bear, will be copied. Note there are RBAC restrictions on determining which workflow job template node is copied. In specific, a workflow job template is allowed to be copied if the user has at least read permission on all related resources like credential and job template. On the other hand, schedules and notification templates of the original workflow job template will not be copied nor shared, and the name of the created workflow job template is the original name plus a special-formatted suffix to indicate its copy origin as well as the copy time, such as 'copy_from_name@10:30:00 am'. +Workflow job templates can be copied by POSTing to endpoint `/workflow_job_templates/\d+/copy/`. After copy finished, the resulting new workflow job template will have identical fields including description, extra_vars, and survey-related fields (survey_spec and survey_enabled). More importantly, workflow job template node of the original workflow job template, as well as the topology they bear, will be copied. Note there are RBAC restrictions on copying workflow job template nodes. A workflow job template is allowed to be copied if the user has permission to add an equivalent workflow job template. If the user performing the copy does not have access to a node's related resources (job template, inventory, or credential), those related fields will be null in the copy's version of the node. Schedules and notification templates of the original workflow job template will not be copied nor shared, and the name of the created workflow job template is the original name plus a special-formatted suffix to indicate its copy origin as well as the copy time, such as 'copy_from_name@10:30:00 am'. -Worflow jobs cannot be copied directly, instead a workflow job is implicitly copied when it needs to relaunch. Relaunching an existing workflow job is done by POSTing to endpoint `/workflow_jobs/\d+/relaunch/`. What happens next is the original workflow job is copied to create a new workflow job. The new workflow job then gets a copy of all nodes of the original as well as the topology they bear. Finally the full-fledged new workflow job is triggered to run, thus fulfilling the purpose of relaunch. +Workflow jobs cannot be copied directly, instead a workflow job is implicitly copied when it needs to relaunch. Relaunching an existing workflow job is done by POSTing to endpoint `/workflow_jobs/\d+/relaunch/`. What happens next is the original workflow job is copied to create a new workflow job. The new workflow job then gets a copy of all nodes of the original as well as the topology they bear. Finally the full-fledged new workflow job is triggered to run, thus fulfilling the purpose of relaunch. Survey password-type answers should also be redacted in the relaunched version of the workflow job. ## Test Coverage ### CRUD-related diff --git a/requirements/requirements_ansible.in b/requirements/requirements_ansible.in index 2d381c955b..5497b2a7b1 100644 --- a/requirements/requirements_ansible.in +++ b/requirements/requirements_ansible.in @@ -7,5 +7,6 @@ boto==2.45.0 psphere==0.5.2 psutil==5.0.0 pyvmomi==6.5 +pywinrm[kerberos]==0.2.2 secretstorage==2.3.1 shade==1.13.1 diff --git a/requirements/requirements_ansible.txt b/requirements/requirements_ansible.txt index 59a7fe9544..fef057d56b 100644 --- a/requirements/requirements_ansible.txt +++ b/requirements/requirements_ansible.txt @@ -64,8 +64,10 @@ msrestazure==0.4.6 # via azure-common munch==2.0.4 # via shade netaddr==0.7.18 # via oslo.config, oslo.utils, python-neutronclient netifaces==0.10.5 # via oslo.utils, shade +ntlm-auth==1.0.2 # via requests-ntlm oauthlib==2.0.1 # via requests-oauthlib openstacksdk==0.9.11 # via python-openstackclient +ordereddict==1.1 # via ntlm-auth os-client-config==1.24.0 # via openstacksdk, osc-lib, python-magnumclient, python-neutronclient, shade os-diskconfig-python-novaclient-ext==0.1.3 # via rackspace-novaclient os-networksv2-python-novaclient-ext==0.26 # via rackspace-novaclient @@ -83,6 +85,7 @@ psutil==5.0.0 pyasn1==0.1.9 # via cryptography pycparser==2.17 # via cffi PyJWT==1.4.2 # via adal +pykerberos==1.1.13 # via requests-kerberos pyparsing==2.1.10 # via cliff, cmd2, oslo.utils python-cinderclient==1.9.0 # via python-openstackclient, shade python-dateutil==2.6.0 # via adal, azure-storage @@ -100,24 +103,28 @@ python-swiftclient==3.2.0 # via python-heatclient, python-troveclient, shade python-troveclient==2.7.0 # via shade pytz==2016.10 # via babel, oslo.serialization, oslo.utils pyvmomi==6.5 +pywinrm[kerberos]==0.2.2 PyYAML==3.12 # via cliff, os-client-config, psphere, python-heatclient, python-ironicclient, python-mistralclient rackspace-auth-openstack==1.3 # via rackspace-novaclient rackspace-novaclient==2.1 rax-default-network-flags-python-novaclient-ext==0.4.0 # via rackspace-novaclient rax-scheduled-images-python-novaclient-ext==0.3.1 # via rackspace-novaclient +requests-kerberos==0.11.0 # via pywinrm +requests-ntlm==1.0.0 # via pywinrm requests-oauthlib==0.7.0 # via msrest -requests==2.11.1 # via adal, azure-servicebus, azure-servicemanagement-legacy, azure-storage, keystoneauth1, msrest, python-cinderclient, python-designateclient, python-glanceclient, python-heatclient, python-ironicclient, python-keystoneclient, python-magnumclient, python-mistralclient, python-neutronclient, python-novaclient, python-swiftclient, python-troveclient, pyvmomi, requests-oauthlib +requests==2.11.1 # via adal, azure-servicebus, azure-servicemanagement-legacy, azure-storage, keystoneauth1, msrest, python-cinderclient, python-designateclient, python-glanceclient, python-heatclient, python-ironicclient, python-keystoneclient, python-magnumclient, python-mistralclient, python-neutronclient, python-novaclient, python-swiftclient, python-troveclient, pyvmomi, pywinrm, requests-kerberos, requests-ntlm, requests-oauthlib requestsexceptions==1.1.3 # via os-client-config, shade rfc3986==0.4.1 # via oslo.config secretstorage==2.3.1 shade==1.13.1 simplejson==3.10.0 # via osc-lib, python-cinderclient, python-neutronclient, python-novaclient, python-troveclient -six==1.10.0 # via cliff, cryptography, debtcollector, keystoneauth1, mock, openstacksdk, osc-lib, oslo.config, oslo.i18n, oslo.serialization, oslo.utils, python-cinderclient, python-dateutil, python-designateclient, python-glanceclient, python-heatclient, python-ironicclient, python-keystoneclient, python-magnumclient, python-mistralclient, python-neutronclient, python-novaclient, python-openstackclient, python-swiftclient, python-troveclient, pyvmomi, shade, stevedore, warlock +six==1.10.0 # via cliff, cryptography, debtcollector, keystoneauth1, mock, ntlm-auth, openstacksdk, osc-lib, oslo.config, oslo.i18n, oslo.serialization, oslo.utils, python-cinderclient, python-dateutil, python-designateclient, python-glanceclient, python-heatclient, python-ironicclient, python-keystoneclient, python-magnumclient, python-mistralclient, python-neutronclient, python-novaclient, python-openstackclient, python-swiftclient, python-troveclient, pyvmomi, pywinrm, shade, stevedore, warlock stevedore==1.19.1 # via cliff, keystoneauth1, openstacksdk, osc-lib, oslo.config, python-designateclient, python-keystoneclient, python-magnumclient suds==0.4 # via psphere unicodecsv==0.14.1 # via cliff warlock==1.2.0 # via python-glanceclient wrapt==1.10.8 # via debtcollector, positional +xmltodict==0.10.2 # via pywinrm # The following packages are considered to be unsafe in a requirements file: # setuptools # via cryptography