diff --git a/MANIFEST.in b/MANIFEST.in index 581c441eef..ac84fdd302 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,7 +1,7 @@ recursive-include awx *.py recursive-include awx/static *.ico recursive-include awx/templates *.html -recursive-include awx/ui *.html *.js +recursive-include awx/ui *.html recursive-include awx/ui/static *.css *.ico *.png *.gif *.jpg recursive-include awx/ui/static *.eot *.svg *.ttf *.woff *.otf recursive-include awx/lib/site-packages * @@ -10,6 +10,7 @@ recursive-include config/deb * recursive-include config/rpm * recursive-exclude awx devonly.py* recursive-exclude awx/settings local_settings.py* +include awx/ui/static/js/awx-min.js include COPYING prune awx/public prune awx/projects diff --git a/Makefile b/Makefile index b61f420d9c..218804801c 100644 --- a/Makefile +++ b/Makefile @@ -31,6 +31,7 @@ clean: rm -rf dist/* rm -rf build rpm-build *.egg-info rm -rf debian deb-build + rm -f awx/ui/static/js/awx-min.js find . -type f -regex ".*\.py[co]$$" -delete # Fetch from origin, rebase local commits on top of origin commits. @@ -128,7 +129,10 @@ release_clean: -(rm *.tar) -(rm -rf ($RELEASE)) -sdist: clean +minjs: clean + (cd tools/ui/ && ./compile.sh) + +sdist: clean minjs if [ "$(OFFICIAL)" = "yes" ] ; then \ $(PYTHON) setup.py release_build; \ else \ diff --git a/awx/ui/static/js/awx-min.js b/awx/ui/static/js/awx-min.js deleted file mode 100644 index 3c1ff585f0..0000000000 --- a/awx/ui/static/js/awx-min.js +++ /dev/null @@ -1,386 +0,0 @@ -/********************************************* - * Copyright (c) 2013 AnsibleWorks, Inc. - * All rights reserved - * - * awx-min.js - * - * master-6fcbfb1, Mon Jul 15 14:35:54 2013 -0400 - * - */ -var urlPrefix="/static/"; -angular.module("ansible","RestServices AuthService Utilities OrganizationFormDefinition UserFormDefinition FormGenerator OrganizationListDefinition UserListDefinition ListGenerator PromptDialog ApiLoader RelatedSearchHelper RelatedPaginateHelper SearchHelper PaginateHelper RefreshHelper AdminListDefinition AWDirectives InventoriesListDefinition InventoryFormDefinition InventoryHelper AWFilters HostFormDefinition HostListDefinition GroupFormDefinition GroupListDefinition TeamsListDefinition TeamFormDefinition TeamHelper CredentialsListDefinition CredentialFormDefinition LookUpHelper JobTemplatesListDefinition JobTemplateFormDefinition JobTemplateHelper ProjectsListDefinition ProjectFormDefinition PermissionFormDefinition PermissionListDefinition JobsListDefinition JobFormDefinition JobEventsListDefinition JobEventFormDefinition JobHostDefinition GroupsHelper HostsHelper ParseHelper ChildrenHelper EventsHelper ProjectPathHelper md5Helper AccessHelper".split(" ")).config(["$routeProvider",function(k){k.when("/jobs", -{templateUrl:urlPrefix+"partials/jobs.html",controller:JobsListCtrl}).when("/jobs/:id",{templateUrl:urlPrefix+"partials/jobs.html",controller:JobsEdit}).when("/jobs/:id/job_events",{templateUrl:urlPrefix+"partials/jobs.html",controller:JobEventsList}).when("/jobs/:id/job_host_summaries",{templateUrl:urlPrefix+"partials/jobs.html",controller:JobHostSummaryList}).when("/jobs/:job_id/job_events/:event_id",{templateUrl:urlPrefix+"partials/jobs.html",controller:JobEventsEdit}).when("/job_templates",{templateUrl:urlPrefix+ -"partials/job_templates.html",controller:JobTemplatesList}).when("/job_templates/add",{templateUrl:urlPrefix+"partials/job_templates.html",controller:JobTemplatesAdd}).when("/job_templates/:id",{templateUrl:urlPrefix+"partials/job_templates.html",controller:JobTemplatesEdit}).when("/projects",{templateUrl:urlPrefix+"partials/projects.html",controller:ProjectsList}).when("/projects/add",{templateUrl:urlPrefix+"partials/projects.html",controller:ProjectsAdd}).when("/projects/:id",{templateUrl:urlPrefix+ -"partials/projects.html",controller:ProjectsEdit}).when("/inventories",{templateUrl:urlPrefix+"partials/inventories.html",controller:InventoriesList}).when("/inventories/add",{templateUrl:urlPrefix+"partials/inventories.html",controller:InventoriesAdd}).when("/inventories/:id",{templateUrl:urlPrefix+"partials/inventories.html",controller:InventoriesEdit}).when("/organizations",{templateUrl:urlPrefix+"partials/organizations.html",controller:OrganizationsList}).when("/organizations/add",{templateUrl:urlPrefix+ -"partials/organizations.html",controller:OrganizationsAdd}).when("/organizations/:organization_id",{templateUrl:urlPrefix+"partials/organizations.html",controller:OrganizationsEdit}).when("/organizations/:organization_id/admins",{templateUrl:urlPrefix+"partials/organizations.html",controller:AdminsList}).when("/organizations/:organization_id/users",{templateUrl:urlPrefix+"partials/users.html",controller:UsersList}).when("/organizations/:organization_id/users/add",{templateUrl:urlPrefix+"partials/users.html", -controller:UsersAdd}).when("/organizations/:organization_id/users/:user_id",{templateUrl:urlPrefix+"partials/users.html",controller:UsersEdit}).when("/teams",{templateUrl:urlPrefix+"partials/teams.html",controller:TeamsList}).when("/teams/add",{templateUrl:urlPrefix+"partials/teams.html",controller:TeamsAdd}).when("/teams/:team_id",{templateUrl:urlPrefix+"partials/teams.html",controller:TeamsEdit}).when("/teams/:team_id/permissions/add",{templateUrl:urlPrefix+"partials/teams.html",controller:PermissionsAdd}).when("/teams/:team_id/permissions", -{templateUrl:urlPrefix+"partials/teams.html",controller:PermissionsList}).when("/teams/:team_id/permissions/:permission_id",{templateUrl:urlPrefix+"partials/teams.html",controller:PermissionsEdit}).when("/teams/:team_id/users",{templateUrl:urlPrefix+"partials/teams.html",controller:UsersList}).when("/teams/:team_id/users/:user_id",{templateUrl:urlPrefix+"partials/teams.html",controller:UsersEdit}).when("/teams/:team_id/projects",{templateUrl:urlPrefix+"partials/teams.html",controller:ProjectsList}).when("/teams/:team_id/projects/add", -{templateUrl:urlPrefix+"partials/teams.html",controller:ProjectsAdd}).when("/teams/:team_id/projects/:project_id",{templateUrl:urlPrefix+"partials/teams.html",controller:ProjectsEdit}).when("/teams/:team_id/credentials",{templateUrl:urlPrefix+"partials/teams.html",controller:CredentialsList}).when("/teams/:team_id/credentials/add",{templateUrl:urlPrefix+"partials/teams.html",controller:CredentialsAdd}).when("/teams/:team_id/credentials/:credential_id",{templateUrl:urlPrefix+"partials/teams.html", -controller:CredentialsEdit}).when("/credentials",{templateUrl:urlPrefix+"partials/credentials.html",controller:CredentialsList}).when("/credentials/:credential_id",{templateUrl:urlPrefix+"partials/credentials.html",controller:CredentialsEdit}).when("/users",{templateUrl:urlPrefix+"partials/users.html",controller:UsersList}).when("/users/add",{templateUrl:urlPrefix+"partials/users.html",controller:UsersAdd}).when("/users/:user_id",{templateUrl:urlPrefix+"partials/users.html",controller:UsersEdit}).when("/users/:user_id/credentials", -{templateUrl:urlPrefix+"partials/users.html",controller:CredentialsList}).when("/users/:user_id/permissions/add",{templateUrl:urlPrefix+"partials/users.html",controller:PermissionsAdd}).when("/users/:user_id/permissions",{templateUrl:urlPrefix+"partials/users.html",controller:PermissionsList}).when("/users/:user_id/permissions/:permission_id",{templateUrl:urlPrefix+"partials/users.html",controller:PermissionsEdit}).when("/users/:user_id/credentials/add",{templateUrl:urlPrefix+"partials/teams.html", -controller:CredentialsAdd}).when("/teams/:user_id/credentials/:credential_id",{templateUrl:urlPrefix+"partials/teams.html",controller:CredentialsEdit}).when("/login",{templateUrl:urlPrefix+"partials/login-dialog.html",controller:Authenticate}).when("/logout",{templateUrl:urlPrefix+"partials/login-dialog.html",controller:Authenticate}).otherwise({redirectTo:"/"})}]).run(["$rootScope","CheckLicense","$location","Authorization","LoadBasePaths",function(k,m,h,g,c){c();k.breadcrumbs=[];k.crumbCache=[]; -k.$on("$routeChangeStart",function(c,f,e){!1==g.isTokenValid()?f.templateUrl!=urlPrefix+"partials/login.html"&&h.path("/login"):((void 0==k.current_user||null==k.current_user)&&g.restoreUserInfo(),m());c=h.path().replace(/^\//,"").split("/")[0];""==c?$('.nav-tabs a[href="#organizations"]').tab("show"):(c.replace(/\_/g," "),$('.nav-tabs a[href="#'+c+'"]').tab("show"))});g.isTokenValid()||h.path("/login");c=h.path().replace(/^\//,"").split("/")[0];""==c?(c="organizations",h.path("/organizations")): -c.replace(/\_/g," ");$('.nav-tabs a[href="#'+c+'"]').tab("show");k.viewCurrentUser=function(){h.path("/users/"+k.current_user.id)}}]);var $AnsibleConfig={session_timeout:3600,tooltip_delay:{show:500,hide:100},debug_mode:!0};function AdminsList(k,m,h,g,c,p,f,e,l,a,d,b,y,v,A){k=A("organizations")+c.organization_id+"/users/";var u=l.inject(e,{mode:"select"});u.selected=[];u.PostRefreshRemove&&u.PostRefreshRemove();u.PostRefreshRemove=u.$on("PostRefresh",function(){$("tr.success").each(function(a){a=$(this).attr("ng-class");u[a]=""})});b({scope:u,set:"admins",list:e,url:k});y({scope:u,list:e,url:k});u.search(e.iterator);a();u.finishSelection=function(){var a=A("organizations")+c.organization_id+"/admins/";p.setUrl(a);u.queue= -[];u.$on("callFinished",function(){if(u.queue.length==u.selected.length){$('input[type="checkbox"]').prop("checked",!1);u.selected=[];for(var a=0,b=0;b -a[d].event_level)a[d].ngclick="toggleChildren("+a[d].id+', "'+a[d].related.children+'")',a[d].ngicon="icon-collapse-alt",a[d]["class"]="parentNode";else{a[d]["class"]="childNode";b=a[d];var c=a[d].event_data,f="";if(c.res){var n=void 0,n=void 0,l=!1;if("string"==typeof c.res)n=(n=c.res.match(/\n/g))?n.length:1,l=!0,f+="\n",f+='\n";else{var g=void 0;for(g in c.res){if(("msg"==g||"stdout"==g||"stderr"== -g)&&null!==c.res[g]&&""!==c.res[g]){f+="\n";n=(n=c.res[g].match(/\n/g))?n.length:1;f+='\n";l=!0}if("results"==g&&Array.isArray(c.res[g])&&0Results:\n";l="";for(n=0;n'+l+"\n";l=!0}"rc"==g&&0!=c.res[g]&&(f+="\n",f+='\n',l=!0)}}f=l?'
\n'+f+"
\n":""}f=c.host?''+c.host+"\n"+f:""==f?null:f;b.event_detail=f}a[d].show=!0;a[d].spaces=24*a[d].event_level;q.jobevents[d].status=q.jobevents[d].failed?"error":q.jobevents[d].changed?"changed":"success";b=new Date(a[d].created); -a[d].created=B(b)}});b({scope:q,set:"jobevents",list:e,url:k});y({scope:q,list:e,url:k});c.host&&(q[e.iterator+"SearchField"]="host",q[e.iterator+"SearchValue"]=c.host,q[e.iterator+"SearchFieldLabel"]=e.fields.host.label);q.search(e.iterator);q.toggleChildren=function(a,b){s({scope:q,list:e,id:a,children:b})};a();q.viewJobEvent=function(a){n({event_id:a})};q.refresh=function(){q.expand=!0;q.search(e.iterator)};q.jobDetails=function(){h.path("/jobs/"+c.id)};q.jobSummary=function(){h.path("/jobs/"+ -c.id+"/job_host_summaries")}}JobEventsList.$inject="$scope $rootScope $location $log $routeParams Rest Alert JobEventList GenerateList LoadBreadCrumbs Prompt SearchInit PaginateInit ReturnToCaller ClearScope ProcessErrors GetBasePath LookUpInit ToggleChildren EventView FormatDate".split(" "); -function JobEventsEdit(k,m,h,g,c,p,f,e,l,a,d,b,y,v,A){y("htmlTemplate");var u=e.inject(f,{mode:"edit",related:!0});e.reset();k=v("base")+"job_events/"+p.event_id+"/";g.path().replace(/^\//,"").split("/");l.setUrl(k);l.get().success(function(a,d,c,e){b({path:"/job_events/"+p.event_id,title:a.event});for(var l in f.fields)"status"==l?u.status=a.failed?"error":"success":"event_data"==l?u.event_data=JSON.stringify(a.event_data,void 0,"\t"):"created"==l?u.created=A(new Date(a.created)):a[l]&&(u[l]=a[l])}).error(function(a, -b,c,e){d(u,a,b,f,{hdr:"Error!",msg:"Failed to retrieve event detail: "+p.event_id+". GET status: "+b})})}JobEventsEdit.$inject="$scope $rootScope $compile $location $log $routeParams JobEventForm GenerateForm Rest Alert ProcessErrors LoadBreadCrumbs ClearScope GetBasePath FormatDate".split(" ");function JobHostSummaryList(k,m,h,g,c,p,f,e,l,a,d,b,y,v,A,u,C){A("htmlTemplate");k=C("jobs")+c.id+"/job_host_summaries/";h.path().replace(/^\//,"").split("/");var t=l.inject(e,{mode:"edit"});t.selected=[];t.PostRefreshRemove&&t.PostRefreshRemove();t.PostRefershRemove=t.$on("PostRefresh",function(){for(var a=0;aEnter variables using either JSON or YAML syntax. Use the radio button to toggle between the two.

JSON:
\n
{
"somevar": "somevalue",
"password": "magic"
}
\nYAML:
\n
---
somevar: somevalue
password: magic
\n

View JSON examples at www.json.org

View YAML examples at ansibleworks.com

', -dataContainer:"#form-modal"}},buttons:{save:{label:"Save",icon:"icon-ok","class":"btn btn-success",ngClick:"formSave()",ngDisabled:!0},reset:{ngClick:"formReset()",label:"Reset",icon:"icon-remove",ngDisabled:!0}},related:{}});angular.module("HostFormDefinition",[]).value("HostForm",{addTitle:"Create Host",editTitle:"{{ name }}",name:"host","class":"horizontal-narrow",well:!1,fields:{name:{label:"Host Name",type:"text",addRequired:!0,editRequired:!0,awPopOver:"

Provide a host name, ip address, or ip address:port. Examples include:

myserver.domain.com
127.0.0.1
10.1.0.140:25
server.example.com:25
",dataTitle:"Host Name",dataPlacement:"right",dataContainer:"#form-modal"},description:{label:"Description", -type:"text",addRequired:!1,editRequired:!1},inventory:{type:"hidden",includeOnEdit:!0,includeOnAdd:!0},variables:{label:"Variables",type:"textarea",addRequired:!1,editRequird:!1,rows:10,"class":"modal-input-xlarge","default":"---",awPopOver:'

Enter variables using either JSON or YAML syntax. Use the radio button to toggle between the two.

JSON:
\n
{
"somevar": "somevalue",
"password": "magic"
}
\nYAML:
\n
---
somevar: somevalue
password: magic
\n

View JSON examples at www.json.org

View YAML examples at ansibleworks.com

', -dataTitle:"Host Variables",dataPlacement:"right",dataContainer:"#form-modal"}},buttons:{save:{label:"Save",icon:"icon-ok","class":"btn-success",ngClick:"formSave()",ngDisabled:!0},reset:{ngClick:"formReset()",label:"Reset",icon:"icon-remove",ngDisabled:!0}},related:{}});angular.module("InventoryFormDefinition",[]).value("InventoryForm",{addTitle:"Create Inventory",editTitle:"{{ inventory_name }}",name:"inventory",well:!0,collapse:!0,collapseTitle:"Edit Inventory",collapseMode:"edit",twoColumns:!0,parseTypeName:"inventoryParseType",fields:{has_active_failures:{label:"Host Status",control:'
Failed jobs
',type:"custom",ngShow:"has_active_failures",readonly:!0,column:1},inventory_name:{realName:"name", -label:"Name",type:"text",addRequired:!0,editRequired:!0,capitalize:!1,column:1},inventory_description:{realName:"description",label:"Description",type:"text",addRequired:!1,editRequired:!1,column:1},organization:{label:"Organization",type:"lookup",sourceModel:"organization",sourceField:"name",addRequired:!0,editRequired:!0,ngClick:"lookUpOrganization()",column:1},inventory_variables:{realName:"variables",label:"Variables",type:"textarea",addRequired:!1,editRequird:!1,rows:10,"class":"modal-input-xlarge", -"default":"---",awPopOver:'

Enter variables using either JSON or YAML syntax. Use the radio button to toggle between the two.

View JSON examples at www.json.org

View YAML examples at ansibleworks.com

',dataTitle:"Inventory Variables",dataPlacement:"bottom",column:2}},buttons:{save:{label:"Save",icon:"icon-ok","class":"btn-success",ngClick:"formSave()",ngDisabled:!0}, -reset:{ngClick:"formReset()",label:"Reset",icon:"icon-remove",ngDisabled:!0}},related:{groups:{type:"tree",open:!0,actions:{}},hosts:{type:"treeview",title:"{{ groupTitle }}",iterator:"host",actions:{select:{ngClick:"selectHost()",icon:"icon-check",label:"Add Existing Host",awToolTip:"Select existing host",ngHide:"createButtonShow == false","class":"btn btn-pad"},create:{ngClick:"createHost()",icon:"icon-plus",label:"Create New Host",awToolTip:"Create a new host",ngHide:"createButtonShow == false", -"class":"btn-success"}},fields:{name:{key:!0,label:"Host Name",ngClick:"editHost({{ host.id }}, '{{ host.name }}')"},has_active_failures:{label:"Failed jobs?",showValue:!1,ngClick:"showEvents('{{ host.name }}', '{{ host.related.last_job }}')",ngShow:"{{ host.has_active_failures }}",icon:"icon-exclamation-sign","class":"active-failures-{{ host.has_active_failures }}",text:"View failures",searchField:"has_active_failures",searchType:"boolean",searchOptions:[{name:"No",value:0},{name:"Yes",value:1}]}}, -fieldActions:{edit:{ngClick:"editHost({{ host.id }}, '{{ host.name }}')",icon:"icon-edit",label:"Edit","class":"btn-success",awToolTip:"Edit host"},"delete":{ngClick:"deleteHost({{ host.id }}, '{{ host.name }}')",icon:"icon-remove",label:"Delete","class":"btn-danger",awToolTip:"Remove host"}}}}});angular.module("JobEventFormDefinition",[]).value("JobEventForm",{editTitle:"{{ id }} - {{ event }}",name:"job_events","class":"horizontal-narrow",well:!1,fields:{status:{labelClass:"job-{{ status }}",icon:"icon-circle",type:"custom",control:'
{{ status }}
',section:"Event"},id:{label:"ID",type:"text",readonly:!0,section:"Event","class":"span1"},created:{label:"Created",type:"text",readonly:!0,section:"Event"},host:{label:"Host",type:"text",readonly:!0, -section:"Event"},task:{label:"Task",type:"text",readonly:!0,section:"Event"},conditional:{label:"Conditional?",type:"checkbox",readonly:!0,section:"Event"},rc:{label:"Return Code",type:"text",readonly:!0,section:"Results","class":"span1"},msg:{label:"Message",type:"textarea",readonly:!0,section:"Results","class":"modal-input-xlarge",rows:1},stdout:{label:"Std Out",type:"textarea",readonly:!0,section:"Results","class":"modal-input-xlarge",rows:1},stderr:{label:"Std Error",type:"textarea",readonly:!0, -section:"Results","class":"modal-input-xlarge",rows:1},start:{label:"Start",type:"text",readonly:!0,section:"Timing"},end:{label:"End",type:"text",readonly:!0,section:"Timing"},delta:{label:"Elapsed",type:"text",readonly:!0,section:"Timing"},module_name:{label:"Name",type:"text",readonly:!0,section:"Module"},module_args:{label:"Arguments",type:"text",readonly:!0,section:"Module"}},buttons:{},related:{}});angular.module("JobFormDefinition",[]).value("JobForm",{addTitle:"Create Job",editTitle:"{{ name }}",name:"jobs",well:!0,twoColumns:!0,fields:{name:{label:"Name",type:"text",addRequired:!0,editRequired:!0,column:1},description:{label:"Description",type:"text",addRequired:!1,editRequired:!1,column:1},job_type:{label:"Job Type",type:"select",ngOptions:"type.label for type in job_type_options","default":"run",addRequired:!0,editRequired:!0,awPopOver:"

When this template is submitted as a job, setting the type to run will execute the playbook, running tasks on the selected hosts.

Setting the type to check will not execute the playbook. Instead, ansible will check playbook syntax, test environment setup and report problems.

", -dataTitle:"Job Type",dataPlacement:"right",column:1},inventory:{label:"Inventory",type:"lookup",sourceModel:"inventory",sourceField:"name",addRequired:!0,editRequired:!0,ngClick:"lookUpInventory()",column:1},project:{label:"Project",type:"lookup",sourceModel:"project",sourceField:"name",addRequired:!0,editRequired:!0,ngClick:"lookUpProject()",column:1},playbook:{label:"Playbook",type:"select",ngOptions:"book for book in playbook_options",id:"playbook-select",addRequired:!0,editRequired:!0,column:1}, -credential:{label:"Credential",type:"lookup",sourceModel:"credential",sourceField:"name",ngClick:"lookUpCredential()",addRequired:!1,editRequired:!1,column:2},forks:{label:"Forks",id:"forks-number",type:"number",integer:!0,min:0,max:100,slider:!0,"class":"input-mini","default":"0",addRequired:!1,editRequired:!1,column:2,awPopOver:"

The number of parallel or simultaneous processes to use while executing the playbook. Provide a value between 0 and 100. A value of zero will use the ansible default setting of 5 parallel processes.

", -dataTitle:"Forks",dataPlacement:"left"},limit:{label:"Limit",type:"text",addRequired:!1,editRequired:!1,column:2,awPopOver:'

Provide a host pattern to further constrain the list of hosts that will be managed or affected by the playbook. Multiple patterns can be separated by ; : or ,

For more information and examples see the Selecting Targets section under Inventory and Patterns in the Ansible documentation.

', -dataTitle:"Limit",dataPlacement:"left"},verbosity:{label:"Verbosity",type:"select",ngOptions:"v.label for v in verbosity_options","default":0,addRequired:!0,editRequired:!0,column:2,awPopOver:"

Control the level of output ansible will produce as the playbook executes.

",dataTitle:"Verbosity",dataPlacement:"left"},variables:{label:"Extra Variables",type:"textarea",rows:6,"class":"span12",addRequired:!1,editRequired:!1,column:2,awPopOver:'

Pass extra command line variables to the playbook. This is the -e or --extra-vars command line parameter for ansible-playbook. Provide key/value pairs using either YAML or JSON.

JSON:
\n
{
"somevar": "somevalue",
"password": "magic"
}
\nYAML:
\n
---
somevar: somevalue
password: magic
\n', -dataTitle:"Extra Variables",dataPlacement:"left"},allow_callbacks:{label:"Allow Callbacks",type:"checkbox",addRequired:!1,editRequird:!1,trueValue:"true",falseValue:"false",ngChange:"toggleCallback('host_config_key')","class":"span12",column:2,awPopOver:'

Create a callback URL a host can use to contact the AWX server and request a configuration update using the job template. The URL will look like the following:

\n

http://your.server.com:999/api/v1/job_templates/1/callback/

The request from the host must be a POST. Here is an example using curl:

\n

curl --data "host_config_key=5a8ec154832b780b9bdef1061764ae5a" http://your.server.com:999/api/v1/job_templates/1/callback/

\n

Note the requesting host must be defined in your inventory. If ansible fails to locate the host either by name or IP address in one of your defined inventories, the request will be denied.

Successful requests will result in an entry on the Jobs tab, where the results and history can be viewed.

', -detailPlacement:"left",dataContainer:"#jobs",dataTitle:"Callback URL"},callback_url:{label:"Callback URL",type:"text",addRequired:!1,editRequired:!1,readonly:!0,column:2,required:!1,"class":"span12",awPopOver:'

Using this URL a host can contact the AWX server and request a configuration update using the job template. The request from the host must be a POST. Here is an example using curl:

\n

curl --data "host_config_key=5a8ec154832b780b9bdef1061764ae5a" http://your.server.com:999/api/v1/job_templates/1/callback/

\n

Note the requesting host must be defined in your inventory. If ansible fails to locate the host either by name or IP address in one of your defined inventories, the request will be denied.

Successful requests will result in an entry on the Jobs tab, where the results and history can be viewed.

', -detailPlacement:"left",dataContainer:"#jobs",dataTitle:"Callback URL"},host_config_key:{label:"Host Config Key",type:"text",ngShow:"allow_callbacks",genMD5:!0,column:2,awPopOver:'

When contacting the AWX server using the callback URL, the calling host must authenticate by including this key in the POST data of the request. Here\'s an example using curl:

\n

curl --data "host_config_key=5a8ec154832b780b9bdef1061764ae5a" http://your.server.com:999/api/v1/job_templates/1/callback/

\n', -detailPlacement:"left",dataContainer:"#jobs"}},buttons:{save:{label:"Save",icon:"icon-ok","class":"btn-success",ngClick:"formSave()",ngDisabled:!0},reset:{ngClick:"formReset()",label:"Reset",icon:"icon-remove",ngDisabled:!0}},statusFields:{status:{label:'Job Status {{ status }}',type:"text",readonly:!0,control:!1},created:{label:"Date",type:"text",readonly:!0},result_stdout:{label:"Standard Out",type:"textarea",readonly:!0, -rows:20,"class":"span12"},result_traceback:{label:"Traceback",type:"textarea",readonly:!0,rows:10,"class":"span12",ngShow:"result_traceback != ''"}},statusActions:{refresh:{label:"Refresh",icon:"icon-refresh",ngClick:"refresh()","class":"btn-small btn-success",awToolTip:"Refresh job status & output",mode:"all"},summary:{label:"Hosts",icon:"icon-th-large",ngClick:"jobSummary()","class":"btn btn-small",awToolTip:"View host summary",mode:"all"},events:{label:"Events",icon:"icon-list-ul",ngClick:"jobEvents()", -"class":"btn btn-small",awToolTip:"Edit job events",mode:"all"}},related:{}});angular.module("JobTemplateFormDefinition",[]).value("JobTemplateForm",{addTitle:"Create Job Templates",editTitle:"{{ name }}",name:"job_templates",twoColumns:!0,well:!0,fields:{name:{label:"Name",type:"text",addRequired:!0,editRequired:!0,column:1},description:{label:"Description",type:"text",addRequired:!1,editRequired:!1,column:1},job_type:{label:"Job Type",type:"select",ngOptions:"type.label for type in job_type_options","default":0,addRequired:!0,editRequired:!0,column:1,awPopOver:"

When this template is submitted as a job, setting the type to run will execute the playbook, running tasks on the selected hosts.

Setting the type to check will not execute the playbook. Instead, ansible will check playbook syntax, test environment setup and report problems.

", -dataTitle:"Job Type",dataPlacement:"right"},inventory:{label:"Inventory",type:"lookup",sourceModel:"inventory",sourceField:"name",addRequired:!0,editRequired:!0,ngClick:"lookUpInventory()",column:1},project:{label:"Project",type:"lookup",sourceModel:"project",sourceField:"name",addRequired:!0,editRequired:!0,ngClick:"lookUpProject()",column:1},playbook:{label:"Playbook",type:"select",ngOptions:"book for book in playbook_options",id:"playbook-select",addRequired:!0,editRequired:!0,column:1},credential:{label:"Credential", -type:"lookup",sourceModel:"credential",sourceField:"name",ngClick:"lookUpCredential()",addRequired:!1,editRequired:!1,column:1},forks:{label:"Forks",id:"forks-number",type:"number",integer:!0,min:0,max:100,slider:!0,"class":"input-mini","default":"0",addRequired:!1,editRequired:!1,column:2,awPopOver:"

The number of parallel or simultaneous processes to use while executing the playbook. Provide a value between 0 and 100. A value of zero will use the ansible default setting of 5 parallel processes.

", -dataTitle:"Forks",dataPlacement:"left"},limit:{label:"Limit",type:"text",addRequired:!1,editRequired:!1,column:2,awPopOver:'

Provide a host pattern to further constrain the list of hosts that will be managed or affected by the playbook. Multiple patterns can be separated by ; : or ,

For more information and examples see the Selecting Targets section under Inventory and Patterns in the Ansible documentation.

', -dataTitle:"Limit",dataPlacement:"left"},verbosity:{label:"Verbosity",type:"select",ngOptions:"v.label for v in verbosity_options","default":0,addRequired:!0,editRequired:!0,column:2,awPopOver:"

Control the level of output ansible will produce as the playbook executes.

",dataTitle:"Verbosity",dataPlacement:"left"},variables:{label:"Extra Variables",type:"textarea",rows:6,"class":"span12",addRequired:!1,editRequired:!1,"default":"---",column:2,awPopOver:'

Pass extra command line variables to the playbook. This is the -e or --extra-vars command line parameter for ansible-playbook. Provide key/value pairs using either YAML or JSON.

JSON:
\n
{
"somevar": "somevalue",
"password": "magic"
}
\nYAML:
\n
---
somevar: somevalue
password: magic
\n', -dataTitle:"Extra Variables",dataPlacement:"left"},allow_callbacks:{label:"Allow Callbacks",type:"checkbox",addRequired:!1,editRequird:!1,trueValue:"true",falseValue:"false",ngChange:"toggleCallback('host_config_key')","class":"span12",column:2,awPopOver:'

Create a callback URL a host can use to contact the AWX server and request a configuration update using the job template. The URL will look like the following:

\n

http://your.server.com:999/api/v1/job_templates/1/callback/

The request from the host must be a POST. Here is an example using curl:

\n

curl --data "host_config_key=5a8ec154832b780b9bdef1061764ae5a" http://your.server.com:999/api/v1/job_templates/1/callback/

\n

Note the requesting host must be defined in your inventory. If ansible fails to locate the host either by name or IP address in one of your defined inventories, the request will be denied.

Successful requests will result in an entry on the Jobs tab, where the results and history can be viewed.

', -detailPlacement:"left",dataContainer:"#job_templates",dataTitle:"Callback URL"},callback_url:{label:"Callback URL",type:"text",addRequired:!1,editRequired:!1,readonly:!0,column:2,required:!1,"class":"span12",awPopOver:'

Using this URL a host can contact the AWX server and request a configuration update using the job template. The request from the host must be a POST. Here is an example using curl:

\n

curl --data "host_config_key=5a8ec154832b780b9bdef1061764ae5a" http://your.server.com:999/api/v1/job_templates/1/callback/

\n

Note the requesting host must be defined in your inventory. If ansible fails to locate the host either by name or IP address in one of your defined inventories, the request will be denied.

Successful requests will result in an entry on the Jobs tab, where the results and history can be viewed.

', -detailPlacement:"left",dataContainer:"#job_templates",dataTitle:"Callback URL"},host_config_key:{label:"Host Config Key",type:"text",ngShow:"allow_callbacks",genMD5:!0,column:2,awPopOver:'

When contacting the AWX server using the callback URL, the calling host must authenticate by including this key in the POST data of the request. Here\'s an example using curl:

\n

curl --data "host_config_key=5a8ec154832b780b9bdef1061764ae5a" http://your.server.com:999/api/v1/job_templates/1/callback/

\n', -detailPlacement:"left",dataContainer:"#job_templates"}},buttons:{save:{label:"Save",icon:"icon-ok","class":"btn-success",ngClick:"formSave()",ngDisabled:!0},reset:{ngClick:"formReset()",label:"Reset",icon:"icon-remove",ngDisabled:!0}},related:{jobs:{type:"collection",title:"Jobs",iterator:"job",index:!1,open:!1,actions:{},fields:{id:{label:"Job ID",key:!0,desc:!0,searchType:"int"},name:{label:"Name",link:!0},description:{label:"Description"},status:{label:"Status",icon:"icon-circle","class":"job-{{ job.status }}", -searchType:"select",searchOptions:[{name:"new",value:"new"},{name:"pending",value:"pending"},{name:"running",value:"running"},{name:"successful",value:"successful"},{name:"error",value:"error"},{name:"failed",value:"failed"},{name:"canceled",value:"canceled"}]}},fieldActions:{edit:{label:"View",ngClick:"edit('jobs', {{ job.id }}, '{{ job.name }}')",icon:"icon-zoom-in"}}}}});angular.module("OrganizationFormDefinition",[]).value("OrganizationForm",{addTitle:"Create Organization",editTitle:"{{ name }}",name:"organization",well:!0,fields:{name:{label:"Name",type:"text",addRequired:!0,editRequired:!0,capitalize:!0},description:{label:"Description",type:"text",addRequired:!1,editRequired:!1}},buttons:{save:{label:"Save",icon:"icon-ok","class":"btn-success",ngClick:"formSave()",ngDisabled:!0},reset:{ngClick:"formReset()",label:"Reset",icon:"icon-remove",ngDisabled:!0}},related:{users:{type:"collection", -title:"Users",iterator:"user",open:!1,actions:{add:{ngClick:"add('users')",label:"Add",icon:"icon-plus",awToolTip:"Add a new user"}},fields:{username:{key:!0,label:"Username"},first_name:{label:"First Name"},last_name:{label:"Last Name"}},fieldActions:{edit:{label:"Edit",ngClick:"edit('users', {{ user.id }}, '{{ user.username }}')",icon:"icon-edit","class":"btn-success",awToolTip:"Edit user"},"delete":{label:"Delete",ngClick:"delete('users', {{ user.id }}, '{{ user.username }}', 'users')",icon:"icon-remove", -"class":"btn-danger",awToolTip:"Remove user"}}},admins:{type:"collection",title:"Administrators",iterator:"admin",open:!1,base:"/users",actions:{add:{ngClick:"add('admins')",icon:"icon-plus",label:"Add",awToolTip:"Add new administrator"}},fields:{username:{key:!0,label:"Username"},first_name:{label:"First Name"},last_name:{label:"Last Name"}},fieldActions:{edit:{label:"Edit",ngClick:"edit('users', {{ admin.id }}, '{{ admin.username }}')",icon:"icon-edit","class":"btn-success",awToolTip:"Edit administrator"}, -"delete":{label:"Delete",ngClick:"delete('admins', {{ admin.id }}, '{{ admin.username }}', 'administrators')",icon:"icon-remove","class":"btn-danger",awToolTip:"Remove administrator"}}}}});angular.module("PermissionFormDefinition",[]).value("PermissionsForm",{addTitle:"Add Permission",editTitle:"{{ name }}",name:"permission",well:!0,fields:{category:{label:"Permission Type",type:"radio",options:[{label:"Inventory",value:"Inventory"},{label:"Deployment",value:"Deploy"}],ngChange:"selectCategory()"},name:{label:"Name",type:"text",addRequired:!0,editRequired:!0,capitalize:!0},description:{label:"Description",type:"text",addRequired:!1,editRequired:!1},user:{label:"User",type:"hidden"}, -team:{label:"Team",type:"hidden"},project:{label:"Project",type:"lookup",sourceModel:"project",sourceField:"name",ngShow:"category == 'Deploy'",ngClick:"lookUpProject()",awRequiredWhen:{variable:"projectrequired",init:"false"}},inventory:{label:"Inventory",type:"lookup",sourceModel:"inventory",sourceField:"name",ngClick:"lookUpInventory()",awRequiredWhen:{variable:"inventoryrequired",init:"true"}},permission_type:{label:"Permission",type:"radio",options:[{label:"Admin",value:"admin",ngShow:"category == 'Inventory'"}, -{label:"Read",value:"read",ngShow:"category == 'Inventory'"},{label:"Write",value:"write",ngShow:"category == 'Inventory'"},{label:"Run",value:"run",ngShow:"category == 'Deploy'"},{label:"Check",value:"check",ngShow:"category == 'Deploy'"}],addRequired:!0,editRequired:!0}},buttons:{save:{label:"Save",icon:"icon-ok","class":"btn-success",ngClick:"formSave()",ngDisabled:!0},reset:{ngClick:"formReset()",label:"Reset",icon:"icon-remove",ngDisabled:!0}},related:{}});angular.module("ProjectFormDefinition",[]).value("ProjectsForm",{addTitle:"Create Project",editTitle:"{{ name }}",name:"project",well:!0,fields:{name:{label:"Name",type:"text",addRequired:!0,editRequired:!0,capitalize:!0},description:{label:"Description",type:"text",addRequired:!1,editRequired:!1},base_dir:{label:"Project Base Path",type:"textarea","class":"span6",showonly:!0,awPopOver:"

Base path used for locating playbooks. Directories found inside this path will be listed in the playbook directory drop-down. Together the base path and selected playbook directory provide the full path used to locate playbooks.

Use PROJECTS_ROOT in your environment settings file to determine the base path value.

", -dataTitle:"Project Base Path",dataPlacement:"right"},local_path:{label:"Playbook Directory",type:"select",id:"local-path-select",ngOptions:"path for path in project_local_paths",addRequired:!0,editRequired:!0,awPopOver:"

Select from the list of directories found in the base path.Together the base path and the playbook directory provide the full path used to locate playbooks.

Use PROJECTS_ROOT in your environment settings file to determine the base path value.

",dataTitle:"Project Path", -dataPlacement:"right"}},buttons:{save:{label:"Save",icon:"icon-ok","class":"btn-success",ngClick:"formSave()",ngDisabled:!0},reset:{ngClick:"formReset()",label:"Reset",icon:"icon-remove",ngDisabled:!0}},related:{}});angular.module("TeamFormDefinition",[]).value("TeamForm",{addTitle:"Create Team",editTitle:"{{ name }}",name:"team",well:!0,collapse:!0,collapseTitle:"Team Settings",collapseMode:"edit",collapseOpen:!0,fields:{name:{label:"Name",type:"text",addRequired:!0,editRequired:!0,capitalize:!0},description:{label:"Description",type:"text",addRequired:!1,editRequired:!1},organization:{label:"Organization",type:"lookup",sourceModel:"organization",sourceField:"name",addRequired:!0,editRequired:!0,ngClick:"lookUpOrganization()"}}, -buttons:{save:{label:"Save",icon:"icon-ok","class":"btn-success",ngClick:"formSave()",ngDisabled:!0},reset:{ngClick:"formReset()",label:"Reset",icon:"icon-remove",ngDisabled:!0}},related:{credentials:{type:"collection",title:"Credentials",iterator:"credential",open:!1,actions:{add:{ngClick:"add('credentials')",icon:"icon-plus",label:"Add",add:"Add a new credential"}},fields:{name:{key:!0,label:"Name"},description:{label:"Description"}},fieldActions:{edit:{label:"Edit",ngClick:"edit('credentials', {{ credential.id }}, '{{ credential.name }}')", -icon:"icon-edit","class":"btn-success",awToolTip:"Modify the credential"},"delete":{label:"Delete",ngClick:"delete('credentials', {{ credential.id }}, '{{ credential.name }}', 'credentials')",icon:"icon-remove","class":"btn-danger",awToolTip:"Remove the credential"}}},permissions:{type:"collection",title:"Permissions",iterator:"permission",open:!1,actions:{add:{ngClick:"add('permissions')",icon:"icon-plus",label:"Add",awToolTip:"Add a permission for this user"}},fields:{name:{key:!0,label:"Name", -ngClick:"edit('permissions', {{ permission.id }}, '{{ permission.name }}')"},inventory:{label:"Inventory",sourceModel:"inventory",sourceField:"name",ngBind:"permission.summary_fields.inventory.name"},project:{label:"Project",sourceModel:"project",sourceField:"name",ngBind:"permission.summary_fields.project.name"},permission_type:{label:"Permission"}},fieldActions:{edit:{label:"Edit",ngClick:"edit('permissions', {{ permission.id }}, '{{ permission.name }}')",icon:"icon-edit","class":"btn-success", -awToolTip:"Edit the permission"},"delete":{label:"Delete",ngClick:"delete('permissions', {{ permission.id }}, '{{ permission.name }}', 'permissions')",icon:"icon-remove","class":"btn-danger",awToolTip:"Delete the permission"}}},projects:{type:"collection",title:"Projects",iterator:"project",open:!1,actions:{add:{ngClick:"add('projects')",icon:"icon-plus",label:"Add"}},fields:{name:{key:!0,label:"Name"},description:{label:"Description"}},fieldActions:{edit:{label:"Edit",ngClick:"edit('projects', {{ project.id }}, '{{ project.name }}')", -icon:"icon-edit","class":"btn-success",awToolTip:"Modify the project"},"delete":{label:"Delete",ngClick:"delete('projects', {{ project.id }}, '{{ project.name }}', 'projects')",icon:"icon-remove","class":"btn-danger",awToolTip:"Remove the project"}}},users:{type:"collection",title:"Users",iterator:"user",open:!1,actions:{add:{ngClick:"add('users')",icon:"icon-plus",label:"Add",awToolTip:"Add a user"}},fields:{username:{key:!0,label:"Username"},first_name:{label:"First Name"},last_name:{label:"Last Name"}}, -fieldActions:{edit:{label:"Edit",ngClick:"edit('users', {{ user.id }}, '{{ user.username }}')",icon:"icon-edit","class":"btn-success",awToolTip:"Edit user"},"delete":{label:"Delete",ngClick:"delete('users', {{ user.id }}, '{{ user.username }}', 'users')",icon:"icon-remove","class":"btn-danger",awToolTip:"Remove user"}}}}});angular.module("UserFormDefinition",[]).value("UserForm",{addTitle:"Create User",editTitle:"{{ username }}",name:"user",well:!0,collapse:!0,collapseTitle:"User Settings",collapseMode:"edit",collapseOpen:!0,fields:{first_name:{label:"First Name",type:"text",addRequired:!0,editRequired:!0,capitalize:!0},last_name:{label:"Last Name",type:"text",addRequired:!0,editRequired:!0,capitalize:!0},email:{label:"Email",type:"email",addRequired:!0,editRequired:!0,autocomplete:!1},organization:{label:"Organization", -type:"lookup",sourceModel:"organization",sourceField:"name",addRequired:!0,editRequired:!0,ngClick:"lookUpOrganization()",excludeMode:"edit"},username:{label:"Username",type:"text",addRequired:!0,editRequired:!0,autocomplete:!1},password:{label:"Password",type:"password",addRequired:!0,editRequired:!1,ngChange:"clearPWConfirm('password_confirm')",autocomplete:!1},password_confirm:{label:"Confirm Password",type:"password",addRequired:!1,editRequired:!1,awPassMatch:!0,associated:"password",autocomplete:!1}, -is_superuser:{label:"Superuser?",type:"checkbox",trueValue:"true",falseValue:"false","default":"false",ngShow:"current_user['is_superuser'] == true"}},buttons:{save:{label:"Save",icon:"icon-ok","class":"btn-success",ngClick:"formSave()",ngDisabled:!0},reset:{ngClick:"formReset()",label:"Reset",icon:"icon-remove",ngDisabled:!0}},related:{credentials:{type:"collection",title:"Credentials",iterator:"credential",open:!1,actions:{add:{ngClick:"add('credentials')",icon:"icon-plus",label:"Add",awToolTip:"Add a credential for this user"}}, -fields:{name:{key:!0,label:"Name"},description:{label:"Description"}},fieldActions:{edit:{label:"Edit",ngClick:"edit('credentials', {{ credential.id }}, '{{ credential.name }}')",icon:"icon-edit","class":"btn-success",awToolTip:"Edit the credential"},"delete":{label:"Delete",ngClick:"delete('credentials', {{ credential.id }}, '{{ credential.name }}', 'credentials')",icon:"icon-remove","class":"btn-danger",awToolTip:"Delete the credential"}}},permissions:{type:"collection",title:"Permissions",iterator:"permission", -open:!1,actions:{add:{ngClick:"add('permissions')",icon:"icon-plus",label:"Add",awToolTip:"Add a permission for this user"}},fields:{name:{key:!0,label:"Name",ngClick:"edit('permissions', {{ permission.id }}, '{{ permission.name }}')"},inventory:{label:"Inventory",sourceModel:"inventory",sourceField:"name",ngBind:"permission.summary_fields.inventory.name"},project:{label:"Project",sourceModel:"project",sourceField:"name",ngBind:"permission.summary_fields.project.name"},permission_type:{label:"Permission"}}, -fieldActions:{edit:{label:"Edit",ngClick:"edit('permissions', {{ permission.id }}, '{{ permission.name }}')",icon:"icon-edit","class":"btn-success",awToolTip:"Edit the permission"},"delete":{label:"Delete",ngClick:"delete('permissions', {{ permission.id }}, '{{ permission.name }}', 'permissions')",icon:"icon-remove","class":"btn-danger",awToolTip:"Delete the permission"}}},admin_of_organizations:{type:"collection",title:"Admin of Organizations",iterator:"adminof",open:!1,base:"/organizations",fields:{name:{key:!0, -label:"Name"},description:{label:"Description"}}},organizations:{type:"collection",title:"Organizations",iterator:"organization",open:!1,fields:{name:{key:!0,label:"Name"},description:{label:"Description"}}},teams:{type:"collection",title:"Teams",iterator:"team",open:!1,fields:{name:{key:!0,label:"Name"},description:{label:"Description"}}},projects:{type:"collection",title:"Projects",iterator:"project",open:!1,fields:{name:{key:!0,label:"Name"},description:{label:"Description"}}}}});angular.module("AccessHelper",["RestServices","Utilities","ngCookies"]).factory("CheckAccess",["$rootScope","Alert","Rest","GetBasePath","ProcessErrors",function(k,m,h,g,c){return function(g){var f=k.current_user,e=!1;f.is_superuser?e=!0:f.related.admin_of_organizations&&(h.setUrl(f.related.admin_of_organizations),h.get().success(function(c,a,d,b){0info@ansibleworks.com for assistance.', -"alert-error",null,!1,!0):void 0!==g.demo&&!0==g.demo&&h("AWX Demo",'Thank you for trying AnsibleWorks AWX. You can use this edition to manage up to 5 hosts. Should you wish to acquire a license for additional servers, please visit ansibleworks.com/ansibleworks-awx, or contact info@ansibleworks.com for assistance.',"alert-info"),void 0!==g.date_warning&& -!0==g.date_warning&&h("License Expired",'Your AnsibleWorks AWX License has expired and is no longer compliant. You can continue, but you will be unable to add any additional hosts. Please visit ansibleworks.com/ansibleworks-awx for license and renewal information, or contact info@ansibleworks.com for assistance.',"alert-info"),void 0!==g.free_instances&& -0>=parseInt(g.free_instances)&&h("License Warning",'Your AnsibleWorks AWX License has reached capacity for the number of managed hosts allowed. You will not be able to add any additional hosts. To extend your license, please visit ansibleworks.com/ansibleworks-awx., or contact info@ansibleworks.com for more information.',"alert-info",null,!0))}}]);angular.module("APIDefaults",["RestServices","Utilities"]).factory("GetAPIDefaults",["Alert","Rest","$rootScope",function(k,m,h){return function(g){function c(c){var a={};for(id in h.apiDefaults)if(id==c||id.iterator==c){a[id]=defaults[id];break}return a}function k(){if(f=={}&&5>e)e++,setTimeout(1E3,k());else if("success"==f.status)return c(g)}var f={},e=0;return null==h.apiDefaults||void 0==h.apiDefaults?(f={},m.setUrl("/api/v1"),m.get().success(function(c,a,d,b){defaults=c;for(var e in defaults)switch(e){case "organizations":dafaults[e].iterator= -"organization";break;case "jobs":defaults[e].iterator="job";break;case "users":defaults[e].iterator="user";break;case "teams":defaults[e].iterator="team";break;case "hosts":defaults[e].iterator="host";break;case "groups":defaults[e].iterator="group";break;case "projects":defaults[e].iterator="project"}h.apiDefaults=defaults;f={status:"success"}}).error(function(c,a,d,b){f={status:"error",msg:"Call to /api/v1 failed. GET returned status: "+a}}),k()):c(g)}}]);angular.module("ChildrenHelper",["RestServices","Utilities"]).factory("ToggleChildren",["Alert","Rest","GetBasePath","ProcessErrors","FormatDate",function(k,m,h,g,c){return function(c){function f(b){a[b].ngicon="icon-collapse-alt";for(var d=b+1;d\n';for(var u=0;u\n',f+='\n",f+='
\n',f+='A value is required!\n',f+='\n',f+="
\n",f+="\n",v=y.associated,y=k.fields[y.associated],a[v]="",f+='
\n',f+='\n",f+='
\n',f+='A value is required!\n',y.awPassMatch&&(f+='Must match Password value\n'),f+='\n',f+="
\n",f+="
\n";f+="\n";d=angular.element(document.getElementById("password-body"));d.html(f);m(d.contents())(a); -$("#password-modal").modal({})}}]).factory("SubmitJob",["PromptPasswords","$compile","Rest","$location","GetBasePath","CredentialList","LookUpInit","JobTemplateForm","ProcessErrors",function(k,m,h,g,c,p,f,e,l){return function(a){function d(a){b.credentialWatchRemove&&b.credentialWatchRemove();var d=(new Date).toISOString(),c=v?v:a.name;h.setUrl(a.related.jobs?a.related.jobs:a.related.job_template+"jobs/");h.post({name:c+" "+d,description:a.description,job_template:a.id,inventory:a.inventory,project:a.project, -playbook:a.playbook,credential:a.credential,forks:a.forks,limit:a.limit,verbosity:a.verbosity,extra_vars:a.extra_vars}).success(function(a,d,c,e){b.job_id=a.id;0There are no unassigned playbook directories in the base project path ("+ -p.base_dir+"). Either the project directory is empty, or all of the contents are already assigned to other AWX projects.

To fix this, log into the AWX server and check out another playbook project from your SCM repository into "+p.base_dir+".

","alert-info")}).error(function(c,l,a,d){g(p,c,l,null,{hdr:"Error!",msg:"Failed to access API config. GET status: "+l})})}}]);angular.module("RefreshRelatedHelper",["RestServices","Utilities"]).factory("RefreshRelated",["Alert","Rest",function(k,m){return function(h){var g=h.scope,c=h.set,p=h.iterator;m.setUrl(h.url);m.get().success(function(f,e,l,a){g[c]=f.results;g[p+"NextUrl"]=f.next;g[p+"PrevUrl"]=f.previous;g[p+"Count"]=f.count;g[p+"PageCount"]=Math.ceil(f.count/g[p+"PageSize"]);g[p+"SearchSpin"]=!1;g[p+"Loading"]=!1}).error(function(f,e,l,a){g[p+"SearchSpin"]=!0;k("Error!","Failed to retrieve related set: "+c+". GET returned status: "+ -e)})}}]);angular.module("RefreshHelper",["RestServices","Utilities"]).factory("Refresh",["Alert","Rest",function(k,m){return function(h){var g=h.scope,c=h.set,p=h.iterator;m.setUrl(h.url);m.get().success(function(f,e,l,a){g[p+"NextUrl"]=f.next;g[p+"PrevUrl"]=f.previous;g[p+"Count"]=f.count;g[p+"PageCount"]=Math.ceil(f.count/g[p+"PageSize"]);g[p+"SearchSpin"]=!1;g[p+"Loading"]=!1;g[c]=f.results;g.$emit("PostRefresh")}).error(function(f,e,l,a){g[p+"SearchSpin"]=!1;k("Error!","Failed to retrieve "+c+". GET returned status: "+ -e)})}}]);angular.module("RelatedPaginateHelper",["RefreshRelatedHelper","ngCookies"]).factory("RelatedPaginateInit",["RefreshRelated","$cookieStore",function(k,m){return function(h){var g=h.scope,c=h.relatedSets,p;for(p in c)(cookieSize=m.get(c[p].iterator+"PageSize"))?g[c[p].iterator+"PageSize"]=cookieSize:(g[c[p].iterator+"Page"]=0,g[c[p].iterator+"PageSize"]=10);g.nextSet=function(c,e){g[e+"Page"]++;k({scope:g,set:c,iterator:e,url:g[e+"NextUrl"]})};g.prevSet=function(c,e){g[e+"Page"]--;k({scope:g,set:c, -iterator:e,url:g[e+"PrevUrl"]})};g.changePageSize=function(f,e){var l;g[e+"Page"]=0;for(var a in c)if(a==f){l=c[a].url;break}m.put(e+"PageSize",g[e+"PageSize"]);l=l.replace(/\/\?.*$/,"/");l+=g[e+"SearchParams"]?g[e+"SearchParams"]+"&page_size="+g[e+"PageSize"]:"?page_size="+g[e+"PageSize"];k({scope:g,set:f,iterator:e,url:l})}}}]);angular.module("RelatedSearchHelper",["RestServices","Utilities","RefreshRelatedHelper"]).factory("RelatedSearchInit",["Alert","Rest","RefreshRelated",function(k,m,h){return function(g){var c=g.scope,k=g.relatedSets,f=g.form,e,l;for(l in f.related)if("tree"!=f.related[l].type){g=f.related[l].iterator;for(var a in f.related[l].fields)if(f.related[l].fields[a].key){c[g+"SearchField"]=a;c[g+"SearchFieldLabel"]=f.related[l].fields[a].label;break}c[g+"SortOrder"]=null;c[g+"SearchType"]="contains";c[g+ -"SearchTypeLabel"]="Contains";c[g+"SelectShow"]=!1;c[g+"HideSearchType"]=!1;e=c[g+"SearchField"];if(f.related[l].fields[e].searchType&&("boolean"==f.related[l].fields[e].searchType||"select"==f.related[l].fields[e].searchType))c[g+"SelectShow"]=!0,c[g+"SearchSelectOpts"]=list.fields[e].searchOptions;f.related[l].fields[e].searchType&&"int"==f.related[l].fields[e].searchType&&(c[g+"HideSearchType"]=!0);f.related[l].fields[e].searchType&&"gtzero"==f.related[l].fields[e].searchType&&(c[g+"InputHide"]= -!0)}c.setSearchField=function(a,b,e){for(var l in f.related)if(f.related[l].iterator==a)var g=f.related[l].fields[b];c[a+"SearchFieldLabel"]=e;c[a+"SearchField"]=b;c[a+"SearchValue"]="";c[a+"SelectShow"]=!1;c[a+"HideSearchType"]=!1;c[a+"InputHide"]=!1;void 0!==g.searchType&&"gtzero"==g.searchType&&(c[a+"InputHide"]=!0);if(void 0!==g.searchType&&("boolean"==g.searchType||"select"==g.searchType))c[a+"SelectShow"]=!0,c[a+"SearchSelectOpts"]=g.searchOptions;void 0!==g.searchType&&"int"==g.searchType&& -(c[a+"HideSearchType"]=!0);c.search(a)};c.setSearchType=function(a,b,e){c[a+"SearchTypeLabel"]=e;c[a+"SearchType"]=b;c.search(a)};c.search=function(a){c[a+"SearchSpin"]=!0;c[a+"Loading"]=!0;var b,e,l,g;for(g in k)if(k[g].iterator==a){b=g;e=k[g].url;for(var m in f.related[g].fields)f.related[g].fields[m].key&&(l=f.related[g].fields[m].desc?"-"+m:m);break}l=null==c[a+"SortOrder"]?l:c[a+"SortOrder"];g=f.related[b].fields[c[a+"SearchField"]];if(!1==c[a+"SelectShow"]&&""!=c[a+"SearchValue"]&&void 0!=c[a+ -"SearchValue"]||c[a+"SelectShow"]&&c[a+"SearchSelectValue"]||g.searchType&&"gtzero"==g.searchType){c[a+"SearchParams"]=g.sourceModel?"?"+g.sourceModel+"__"+g.sourceField+"__":g.searchField?"?"+g.searchField+"__":"?"+c[a+"SearchField"]+"__";c[a+"SearchParams"]=g.searchType&&("int"==g.searchType||"boolean"==g.searchType)?c[a+"SearchParams"]+"int=":g.searchType&&"gtzero"==g.searchType?c[a+"SearchParams"]+"gt=0":c[a+"SearchParams"]+(c[a+"SearchType"]+"=");if(g.searchType&&("boolean"==g.searchType||"select"== -g.searchType))c[a+"SearchParams"]+=c[a+"SearchSelectValue"].value;else if(void 0==g.searchType||"gtzero"==g.searchType)c[a+"SearchParams"]+=escape(c[a+"SearchValue"]);c[a+"SearchParams"]+=l?"&order_by="+escape(l):""}else c[a+"SearchParams"]="",c[a+"SearchParams"]+=l?"?order_by="+escape(l):"";c[a+"Page"]=0;e+=c[a+"SearchParams"];e+=c[a+"PageSize"]?"&page_size="+c[a+"PageSize"]:"";h({scope:c,set:b,iterator:a,url:e})};c.sort=function(a,b){var e;$("."+a+" .list-header").each(function(c){$(this).attr("id")!= -a+"-"+b+"-header"&&$(this).find("i").attr("class","icon-sort")});var l=$("#"+a+"-"+b+"-header i"),g="";l.hasClass("icon-sort")?(l.removeClass("icon-sort"),l.addClass("icon-sort-up")):l.hasClass("icon-sort-up")?(l.removeClass("icon-sort-up"),l.addClass("icon-sort-down"),g="-"):l.hasClass("icon-sort-down")&&(l.removeClass("icon-sort-down"),l.addClass("icon-sort-up"));for(var h in f.related)f.related[h].iterator==a&&(e=f.related[h].fields[b].sourceModel?g+f.related[h].fields[b].sourceModel+"__"+f.related[h].fields[b].sourceModel: -g+b);c[a+"SortOrder"]=e;c.search(a)}}}]);angular.module("SearchHelper",["RestServices","Utilities","RefreshHelper"]).factory("SearchInit",["Alert","Rest","Refresh",function(k,m,h){return function(g){var c=g.scope,k=g.set,f=g.url,e=g.list;g=g.iterator?g.iterator:e.iterator;var l;for(fld in e.fields)if(e.fields[fld].key){if(e.fields[fld].sourceModel){var a=e.fields[fld].sourceModel+"__"+e.fields[fld].sourceField;l=e.fields[fld].desc?"-"+a:a}else l=e.fields[fld].desc?"-"+fld:fld;if(void 0==e.fields[fld].searchable||!0==e.fields[fld].searchable)c[g+ -"SearchField"]=fld,c[g+"SearchFieldLabel"]=e.fields[fld].label;break}if(!c[g+"SearchField"])for(fld in e.fields)if(void 0==e.fields[fld].searchable||!0==e.fields[fld].searchable){c[g+"SearchField"]=fld;c[g+"SearchFieldLabel"]=e.fields[fld].label;break}c[g+"SearchType"]="icontains";c[g+"SearchTypeLabel"]="Contains";c[g+"SearchParams"]="";c[g+"SearchValue"]="";c[g+"SelectShow"]=!1;c[g+"HideSearchType"]=!1;a=c[g+"SearchField"];if(e.fields[a].searchType&&("boolean"==e.fields[a].searchType||"select"== -e.fields[a].searchType))c[g+"SelectShow"]=!0,c[g+"SearchSelectOpts"]=e.fields[a].searchOptions;e.fields[a].searchType&&"int"==e.fields[a].searchType&&(c[g+"HideSearchType"]=!0);e.fields[a].searchType&&"gtzero"==e.fields[a].searchType&&(c[g+"InputHide"]=!0);c.setSearchField=function(a,b,l){c[a+"SearchFieldLabel"]=l;c[a+"SearchField"]=b;c[a+"SearchValue"]="";c[a+"SelectShow"]=!1;c[a+"HideSearchType"]=!1;c[a+"InputHide"]=!1;e.fields[b].searchType&&"gtzero"==e.fields[b].searchType&&(c[a+"InputHide"]= -!0);if(e.fields[b].searchType&&("boolean"==e.fields[b].searchType||"select"==e.fields[b].searchType))c[a+"SelectShow"]=!0,c[a+"SearchSelectOpts"]=e.fields[b].searchOptions;e.fields[b].searchType&&"int"==e.fields[b].searchType&&(c[a+"HideSearchType"]=!0);c.search(a)};c.setSearchType=function(a,b,e){c[a+"SearchTypeLabel"]=e;c[a+"SearchType"]=b;c.search(a)};c.search=function(a){c[a+"SearchSpin"]=!0;c[a+"Loading"]=!0;c[a+"SearchParms"]="";var b=f;!1==c[a+"SelectShow"]&&""!=c[a+"SearchValue"]&&void 0!= -c[a+"SearchValue"]||c[a+"SelectShow"]&&c[a+"SearchSelectValue"]||e.fields[c[a+"SearchField"]].searchType&&"gtzero"==e.fields[c[a+"SearchField"]].searchType?(c[a+"SearchParams"]=e.fields[c[a+"SearchField"]].searchField?e.fields[c[a+"SearchField"]].searchField+"__":e.fields[c[a+"SearchField"]].sourceModel?e.fields[c[a+"SearchField"]].sourceModel+"__"+e.fields[c[a+"SearchField"]].sourceField+"__":c[a+"SearchField"]+"__",c[a+"SearchParams"]=e.fields[c[a+"SearchField"]].searchType&&("int"==e.fields[c[a+ -"SearchField"]].searchType||"boolean"==e.fields[c[a+"SearchField"]].searchType)?c[a+"SearchParams"]+"int=":e.fields[c[a+"SearchField"]].searchType&&"gtzero"==e.fields[c[a+"SearchField"]].searchType?c[a+"SearchParams"]+"gt=0":c[a+"SearchParams"]+(c[a+"SearchType"]+"="),c[a+"SearchParams"]=e.fields[c[a+"SearchField"]].searchType&&("boolean"==e.fields[c[a+"SearchField"]].searchType||"select"==e.fields[c[a+"SearchField"]].searchType)?c[a+"SearchParams"]+c[a+"SearchSelectValue"].value:c[a+"SearchParams"]+ -escape(c[a+"SearchValue"]),c[a+"SearchParams"]+=l?"&order_by="+escape(l):""):c[a+"SearchParams"]=l?"order_by="+escape(l):"";c[a+"Page"]=0;b=/\/$/.test(b)?b+("?"+c[a+"SearchParams"]):b+("&"+c[a+"SearchParams"]);b=b.replace(/\&\&/,"&");b+=c[a+"PageSize"]?"&page_size="+c[a+"PageSize"]:"";h({scope:c,set:k,iterator:a,url:b})};c.sort=function(a){$(".list-header").each(function(b){$(this).attr("id")!=a+"-header"&&$(this).find("i").attr("class","icon-sort")});var b=$("#"+a+"-header i"),f="";b.hasClass("icon-sort")? -(b.removeClass("icon-sort"),b.addClass("icon-sort-up")):b.hasClass("icon-sort-up")?(b.removeClass("icon-sort-up"),b.addClass("icon-sort-down"),f="-"):b.hasClass("icon-sort-down")&&(b.removeClass("icon-sort-down"),b.addClass("icon-sort-up"));l=e.fields[a].searchField?f+e.fields[a].searchField:e.fields[a].sourceModel?f+e.fields[a].sourceModel+"__"+e.fields[a].sourceField:f+a;c.search(e.iterator)}}}]);angular.module("TeamHelper","RestServices Utilities OrganizationListDefinition SearchHelper PaginateHelper ListGenerator".split(" ")).factory("SetTeamListeners",["Alert","Rest",function(k,m){return function(h){var g=h.scope,c=h.set,k=h.iterator;g.$on("TeamResultFound",function(f,e,l){if(l.length==e.length){key="organization";property="organization_name";for(f=0;f button to create a new user.',editInstructions:"Create a new credential from either the Teams tab or the Users tab. Teams and Users each have an associated set of Credentials.",index:!0, -hover:!0,fields:{name:{key:!0,label:"Name"},description:{label:"Description"},team:{label:"Team",ngBind:"credential.summary_fields.team.name",sourceModel:"team",sourceField:"name"},user:{label:"User",ngBind:"credential.summary_fields.user.usename",sourceModel:"user",sourceField:"username"}},actions:{add:{icon:"icon-plus",label:"Add",mode:"all",ngClick:"addCredential()",basePaths:["teams","users"],"class":"btn-success btn-small",awToolTip:"Create a new credential"}},fieldActions:{edit:{ngClick:"editCredential({{ credential.id }})", -icon:"icon-edit",label:"Edit","class":"btn-small btn-success",awToolTip:"View/Edit credential"},"delete":{ngClick:"deleteCredential({{ credential.id }},'{{ credential.name }}')",icon:"icon-remove",label:"Delete","class":"btn-small btn-danger",awToolTip:"Delete credential"}}});angular.module("GroupListDefinition",[]).value("GroupList",{name:"groups",iterator:"group",selectTitle:"Add Group",editTitle:"Groups",index:!0,well:!1,fields:{name:{key:!0,label:"Name"},description:{label:"Description"}},actions:{add:{label:"Create New Group",icon:"icon-plus",mode:"all",ngClick:"createGroup()","class":"btn-success btn-small",awToolTip:"Create a new group"},help:{awPopOver:"Select groups by clicking on each group you wish to add. Add the selected groups to your inventory or to the selected parent group by clicking the Select button. You can also create a new group by clicking the Create New Group button.", -dataPlacement:"left",dataContainer:"#form-modal",icon:"icon-question-sign",mode:"all","class":"btn-small btn-info",awToolTip:"Click for help",dataTitle:"Adding Groups"}},fieldActions:{edit:{label:"Edit",ngClick:"editGroup({{ group.id }})",icon:"icon-edit","class":"btn-small btn-success",awToolTip:"View/Edit group"},"delete":{label:"Delete",ngClick:"deleteGroup({{ group.id }},'{{ group.name }}')",icon:"icon-remove","class":"btn-small btn-danger",awToolTip:"Delete group"}}});angular.module("HostListDefinition",[]).value("HostList",{name:"hosts",iterator:"host",selectTitle:"Select Host",editTitle:"Hosts",index:!0,well:!0,fields:{name:{key:!0,label:"Host Name",linkTo:"/inventories/{{ inventory_id }}/hosts/{{ host.id }}"},description:{label:"Description"}},actions:{help:{awPopOver:"Select hosts by clicking on each host you wish to add. Add the selected hosts to the group by clicking the Select button.",dataPlacement:"left",dataContainer:"#form-modal",icon:"icon-question-sign", -mode:"all","class":"btn-small btn-info",awToolTip:"Click for help",dataTitle:"Selecting Hosts",iconSize:"large"}},fieldActions:{edit:{label:"Edit",ngClick:"editHost({{ host.id }})",icon:"icon-edit","class":"btn-small btn-success",awToolTip:"View/Edit host"},"delete":{label:"Delete",ngClick:"deleteHost({{ host.id }},'{{ host.name }}')",icon:"icon-remove","class":"btn-small btn-danger",awToolTip:"Delete host"}}});angular.module("InventoriesListDefinition",[]).value("InventoryList",{name:"inventories",iterator:"inventory",selectTitle:"Add Inventories",editTitle:"Inventories",selectInstructions:'Click on a row to select it, and click Finished when done. Use the green button to create a new row.',index:!0,hover:!0,fields:{name:{key:!0,label:"Name"},description:{label:"Description"},organization:{label:"Organization",ngBind:"inventory.summary_fields.organization.name",sourceModel:"organization", -sourceField:"name"},has_active_failures:{label:"Failed Jobs?",showValue:!1,text:"View failures",ngShow:"{{ inventory.has_active_failures }}",icon:"icon-exclamation-sign","class":"active-failures-{{ inventory.has_active_failures }}",ngClick:"viewJobs({{ inventory.id }})",searchField:"has_active_failures",searchType:"boolean",searchOptions:[{name:"No",value:0},{name:"Yes",value:1}],excludeModal:!0}},actions:{add:{label:"Add",icon:"icon-plus",mode:"all",ngClick:"addInventory()","class":"btn-small btn-success", -awToolTip:"Create a new inventory"}},fieldActions:{edit:{label:"Edit",ngClick:"editInventory({{ inventory.id }})",icon:"icon-edit","class":"btn-small btn-success",awToolTip:"View/Edit inventory"},"delete":{label:"Delete",ngClick:"deleteInventory({{ inventory.id }},'{{ inventory.name }}')",icon:"icon-remove","class":"btn-small btn-danger",awToolTip:"Delete inventory"}}});angular.module("JobEventsListDefinition",[]).value("JobEventList",{name:"jobevents",iterator:"jobevent",editTitle:"Job Events",index:!1,hover:!0,hasChildren:!0,filterBy:"{ show: true }",fields:{created:{label:"Date",key:!0,nosort:!0,searchable:!1,link:!1},status:{label:"Status",icon:"icon-circle",showValue:!0,"class":"job-{{ jobevent.status }}",searchField:"failed",searchType:"boolean",searchOptions:[{name:"success",value:0},{name:"error",value:1}],nosort:!0,searchable:!1},event_display:{label:"Event", -hasChildren:!0,ngClick:"toggleChildren({{ jobevent.id }}, '{{ jobevent.related.children }}')",nosort:!0,searchable:!1,ngClass:"{{ jobevent.class }}",appendHTML:"jobevent.event_detail"},host:{label:"Host",ngBind:"jobevent.summary_fields.host.name",searchField:"hosts__name",nosort:!0,searchOnly:!1,id:"job-event-host-header",columnClass:"hidden-phone hidden-tablet"}},actions:{refresh:{ngClick:"refresh()",icon:"icon-refresh",label:"Refresh",awToolTip:"Refresh the page","class":"btn-small btn-success", -mode:"all"},edit:{label:"Details",ngClick:"jobDetails()",icon:"icon-zoom-in","class":"btn btn-small",awToolTip:"Edit job details",mode:"all"},summary:{label:"Hosts",icon:"icon-th-large",ngClick:"jobSummary()","class":"btn btn-small",awToolTip:"View host summary",mode:"all"}},fieldActions:{edit:{label:"View",ngClick:"viewJobEvent({{ jobevent.id }})",icon:"icon-zoom-in","class":"btn-small",awToolTip:"View event details"}}});angular.module("JobHostDefinition",[]).value("JobHostList",{name:"jobhosts",iterator:"jobhost",editTitle:"Job Host Summary",index:!0,hover:!0,fields:{host:{label:"Host",key:!0,sourceModel:"host",sourceField:"name",ngBind:"jobhost.host_name",ngClick:"showEvents('{{ jobhost.summary_fields.host.name }}','{{ jobhost.related.job }}')"},status:{label:"Status",icon:"icon-circle","class":"job-{{ jobhost.status }}",searchField:"failed",searchType:"boolean",searchOptions:[{name:"success",value:0},{name:"error", -value:1}]},ok:{label:"Success",searchable:!1},changed:{label:"Changed",searchable:!1},failures:{label:"Failure",searchType:"gtzero"},dark:{label:"Unreachable",searchable:!1},skipped:{label:"Skipped",searchable:!1}},actions:{refresh:{label:"Refresh",icon:"icon-refresh",ngClick:"refresh()","class":"btn-success btn-small",awToolTip:"Refresh the page",mode:"all"},edit:{label:"Details",icon:"icon-edit",ngClick:"jobDetails()","class":"btn btn-small",awToolTip:"Edit job details",mode:"all"},events:{label:"Events", -icon:"icon-list-ul",ngClick:"jobEvents()","class":"btn btn-small",awToolTip:"View job events",mode:"all"},help:{awPopOver:"
\n
Success
Tasks successfully executed on the host.
\n
Changed
Actions taken on the host.
\n
Failure
Tasks that failed on the host.
\n
Unreachable
Times the ansible server could not reach the host.
\n
Skipped
Tasks bypassed and not performed on the host due to prior task failure or the host being unreachable.
\n
\n", -dataPlacement:"right",dataContainer:".container",icon:"icon-question-sign",mode:"all","class":"btn-info btn-mini btn-help",awToolTip:"Click for help",dataTitle:"Job Host Summary",iconSize:"large"}},fieldActions:{}});angular.module("JobsListDefinition",[]).value("JobList",{name:"jobs",iterator:"job",editTitle:"Jobs",index:!1,hover:!0,"class":"jobs-table",fields:{id:{label:"Job ID",key:!0,desc:!0,searchType:"int"},inventory:{label:"Inventory ID",searchType:"int",searchOnly:!0},name:{label:"Name",link:!0},created:{label:"Date",link:!0,searchable:!1},status:{label:"Status",icon:"icon-circle","class":"job-{{ job.status }}",searchType:"select",searchOptions:[{name:"new",value:"new"},{name:"pending",value:"pending"}, -{name:"running",value:"running"},{name:"successful",value:"successful"},{name:"error",value:"error"},{name:"failed",value:"failed"},{name:"canceled",value:"canceled"}]}},actions:{refresh:{label:"Refresh","class":"btn-success btn-small",ngClick:"refreshJob({{ job.id }})",icon:"icon-refresh",awToolTip:"Refresh the page",mode:"all"}},fieldActions:{summary:{label:"Hosts",icon:"icon-th-large",ngClick:"viewSummary({{ job.id }}, '{{ job.name }}')","class":"btn btn-small",awToolTip:"View host summary",ngDisabled:"job.status == 'new'"}, -events:{label:"Events",icon:"icon-list-ul",mode:"all",ngClick:"viewEvents({{ job.id }}, '{{ job.name }}')","class":"btn btn-small",awToolTip:"View events",ngDisabled:"job.status == 'new'"},edit:{label:"Details",icon:"icon-zoom-in",ngClick:"editJob({{ job.id }}, '{{ job.name }}')","class":"btn btn-small",awToolTip:"View job details"},rerun:{icon:"icon-retweet",mode:"all",ngClick:"submitJob({{ job.id }}, '{{ job.summary_fields.job_template.name }}' )","class":"btn-success btn-small",awToolTip:"Re-run this job"}, -cancel:{icon:"icon-minus-sign",mode:"all",ngClick:"deleteJob({{ job.id }})","class":"btn-danger btn-small",awToolTip:"Cancel job",ngDisabled:"job.status != 'new' && job.status != 'pending' && job.status != 'running'"}}});angular.module("JobTemplatesListDefinition",[]).value("JobTemplateList",{name:"job_templates",iterator:"job_template",selectTitle:"Add Job Template",editTitle:"Job Templates",selectInstructions:'Click on a row to select it, and click Finished when done. Use the green button to create a new row.',index:!0,hover:!0,fields:{name:{key:!0,label:"Name"},description:{label:"Description"}},actions:{add:{label:"Add",icon:"icon-plus",mode:"all",ngClick:"addJobTemplate()","class":"btn-success btn-small", -basePaths:["job_templates"],awToolTip:"Create a new template"}},fieldActions:{edit:{label:"Edit",ngClick:"editJobTemplate({{ job_template.id }})",icon:"icon-edit",awToolTip:"Edit template","class":"btn-small btn-success"},submit:{label:"Launch",icon:"icon-rocket",mode:"all","class":"btn-small btn-success",ngClick:"submitJob({{ job_template.id }})",awToolTip:"Start a job using this template"},"delete":{label:"Delete",ngClick:"deleteJobTemplate({{ job_template.id }},'{{ job_template.name }}')",icon:"icon-remove", -"class":"btn-danger btn-small",awToolTip:"Delete template"}}});angular.module("OrganizationListDefinition",[]).value("OrganizationList",{name:"organizations",iterator:"organization",selectTitle:"Add Organizations",editTitle:"Organizations",hover:!0,index:!0,fields:{name:{key:!0,label:"Name"},description:{label:"Description"}},actions:{add:{label:"Add",icon:"icon-plus",mode:"all",ngClick:"addOrganization()","class":"btn-success btn-small",awToolTip:"Create a new organization"}},fieldActions:{edit:{label:"Edit",ngClick:"editOrganization({{ organization.id }})", -icon:"icon-edit","class":"btn-small btn-success",awToolTip:"View/Edit organization"},"delete":{label:"Delete",ngClick:"deleteOrganization({{ organization.id }},'{{ organization.name }}')",icon:"icon-remove","class":"btn-small btn-danger",awToolTip:"Delete organization"}}});angular.module("PermissionListDefinition",[]).value("PermissionList",{name:"permissions",iterator:"permission",selectTitle:"Add Permission",selectInstructions:'Click on a row to select it, and click Finished when done. Use the green button to create a new row.',editTitle:"Permissions",index:!0,well:!0,fields:{name:{key:!0,label:"Name",ngClick:"editPermission({{ permission.id }})"},inventory:{label:"Inventory",sourceModel:"inventory",sourceField:"name",ngBind:"permission.summary_fields.inventory.name"}, -project:{label:"Project",sourceModel:"project",sourceField:"name",ngBind:"permission.summary_fields.project.name"},permission_type:{label:"Permission"}},actions:{add:{icon:"icon-plus",label:"Add",mode:"all",ngClick:"addPermission()","class":"btn-success btn-small",awToolTip:"Add a new permission"}},fieldActions:{edit:{label:"Edit",ngClick:"editPermission({{ permission.id }})",icon:"icon-edit","class":"btn-small btn-success",awToolTip:"View/Edit permission"},"delete":{label:"Delete",ngClick:"deletePermission({{ permission.id }},'{{ permission.name }}')", -icon:"icon-remove","class":"btn-small btn-danger",awToolTip:"Delete permission"}}});angular.module("ProjectsListDefinition",[]).value("ProjectList",{name:"projects",iterator:"project",selectTitle:"Add Project",editTitle:"{{ name }}",selectInstructions:'Click on a row to select it, and click Finished when done. Use the green button to create a new row.',index:!0,hover:!0,fields:{name:{key:!0,label:"Name"},description:{label:"Description"}},actions:{add:{label:"Add",icon:"icon-plus",mode:"all",ngClick:"addProject()","class":"btn-success btn-small",awToolTip:"Create a new project"}}, -fieldActions:{edit:{label:"Edit",ngClick:"editProject({{ project.id }})",icon:"icon-edit","class":"btn-small btn-success",awToolTip:"View/edit project"},"delete":{label:"Delete",ngClick:"deleteProject({{ project.id }},'{{ project.name }}')",icon:"icon-remove","class":"btn-small btn-danger",awToolTip:"Delete project"}}});angular.module("TeamsListDefinition",[]).value("TeamList",{name:"teams",iterator:"team",selectTitle:"Add Team",editTitle:"Teams",selectInstructions:'Click on a row to select it, and click Finished when done. Use the green button to create a new row.',index:!0,hover:!0,fields:{name:{key:!0,label:"Name"},description:{label:"Description"},organization:{label:"Organization",ngBind:"team.organization_name",sourceModel:"organization",sourceField:"name"}},actions:{add:{label:"Add", -icon:"icon-plus",mode:"all",ngClick:"addTeam()","class":"btn-success btn-small",awToolTip:"Create a new team"}},fieldActions:{edit:{label:"Edit",ngClick:"editTeam({{ team.id }})",icon:"icon-edit","class":"btn-small btn-success",awToolTip:"View/Edit team"},"delete":{label:"Delete",ngClick:"deleteTeam({{ team.id }},'{{ team.name }}')",icon:"icon-remove","class":"btn-small btn-danger",awToolTip:"Delete team"}}});angular.module("UserListDefinition",[]).value("UserList",{name:"users",iterator:"user",selectTitle:"Add Users",editTitle:"Users",selectInstructions:'Check the Select checkbox next to each user to be added, and click Finished when done. Use the green button to create a new user.',index:!0,hover:!0,fields:{username:{key:!0,label:"Username"},first_name:{label:"First Name"},last_name:{label:"Last Name"}},actions:{add:{label:"Add",icon:"icon-plus",mode:"all",ngClick:"addUser()", -basePaths:["organizations","users"],"class":"btn-success btn-small",awToolTip:"Create a new user"}},fieldActions:{edit:{label:"Edit",ngClick:"editUser({{ user.id }})",icon:"icon-edit","class":"btn-small btn-success",awToolTip:"View/Edit user"},"delete":{label:"Delete",ngClick:"deleteUser({{ user.id }},'{{ user.username }}')",icon:"icon-remove","class":"btn-small btn-danger",awToolTip:"Delete user"}}});angular.module("ApiLoader",["ngCookies"]).factory("LoadBasePaths",["$http","$rootScope","$cookieStore","ProcessErrors",function(k,m,h,g){return function(){k.get("/api/").success(function(c,p,f,e){var l=c.current_version;k.get(l).success(function(a,c,b,e){a.base=l;m.defaultUrls=a;h.remove("api");h.put("api",a)}).error(function(a,c,b,e){m.defaultUrls={status:"error"};g(null,a,c,null,{hdr:"Error",msg:"Failed to read "+l+". GET status: "+c})})}).error(function(c,h,f,e){m.defaultUrls={status:"error"}; -g(null,c,h,null,{hdr:"Error",msg:"Failed to read /api. GET status: "+h})})}}]).factory("GetBasePath",["$rootScope","$cookieStore","LoadBasePaths",function(k,m,h){return function(g){null==k.defaultUrls||void 0==k.defaultUrls?(g=m.get("api")[g],h()):g=k.defaultUrls[g];return g}}]);angular.module("AuthService",["ngCookies"]).factory("Authorization",["$http","$rootScope","$location","$cookieStore",function(k,m,h,g){return{setToken:function(c){var h=new Date;h.setTime(h.getTime()+1E3*$AnsibleConfig.session_timeout);g.remove("token");g.remove("token_expire");g.put("token",c);g.put("token_expire",h.getTime());m.userLoggedIn=!0},isTokenValid:function(){var c=!1;if(g.get("token")&&g.get("token_expire")){var h=g.get("token"),f=new Date(g.get("token_expire"));new DateparseInt(m.attr("max"))){g.$setValidity("max",!1);return}return c}g.$setValidity("integer", -!1)})}}}).directive("awRequiredWhen",function(){return{require:"ngModel",link:function(k,m,h,g){function c(){var c=m.val();validity=!0;k[h.awRequiredWhen]&&(null==m.attr("required")||void 0==m.attr("required"))?$(m).attr("required","required"):k[h.awRequiredWhen]||m.removeAttr("required");if(k[h.awRequiredWhen]&&(void 0==c||null==c||""==c))validity=!1;g.$setValidity("required",validity)}k[h.awRequiredWhen]=h.awrequiredInit;c();k.$watch(h.awRequiredWhen,function(){c()});k.$watch($(m).attr("name"), -function(){c()})}}}).directive("awlookup",["Rest",function(k){return{require:"ngModel",link:function(m,h,g,c){c.$parsers.unshift(function(g){if(""!==g){var f=h.attr("data-url"),f=f.replace(/\:value/,escape(g));m[h.attr("data-source")]=null;k.setUrl(f);k.get().then(function(e){e=e.data.results;if(0\n");d=d+('\n"},buildField:function(c,a,d){var b="";if("text"==a.type||"password"==a.type||"email"==a.type)if(!a.readonly||a.readonly&&"edit"==d.mode){b=b+'
\n";b+='\n";b+='
\n';b+=a.clear||a.genMD5? -'
\n':"";if(null===a.control||void 0===a.control||a.control){b+="\n', -b+="
\n");a.genMD5&&(b+=' \n\n',b+="
\n");a.ask&&(b+=' \n");b+="
\n";if("add"==d.mode&&a.addRequired||"edit"==d.mode&&a.editRequired||a.awRequiredWhen)b+='A value is required!\n';"email"==a.type&&(b+='A valid email address is required!\n');a.awPassMatch&&(b+='Must match Password value\n');b+='\n'}b+= -"
\n";b+="\n"}if("textarea"==a.type&&(!a.readonly||a.readonly&&"edit"==d.mode)){b+='
\n";b+='\n";b+='
\n';if("variables"==c||"extra_vars"==c||"inventory_variables"==c)b+='
Parse as:
\n';b+="