@spinnaker/ecs 2026.0.2 → 2026.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import*as e from"angular";import{module as t}from"angular";import{HelpContentsRegistry as n,SETTINGS as a,REST as r,CloudProviderRegistry as i,ConfirmationModalService as s,RecentHistoryService as o,InstanceReader as l,InstanceWriter as c,LoadBalancerServerGroup as d,Spinner as p,CollapsibleSection as u,timestamp as m,AccountTag as g,APPLICATION_STATE_PROVIDER as v,Registry as h,AccountService as f,StageConstants as y,PipelineTemplates as b,SECURITY_GROUP_READER as S,MANAGED_RESOURCE_DETAILS_INDICATOR as k,FirewallLabels as C,LOAD_BALANCER_READ_SERVICE as w,CACHE_INITIALIZER_SERVICE as E,SERVER_GROUP_COMMAND_REGISTRY_PROVIDER as D,SubnetReader as G,NameUtils as A,INSTANCE_TYPE_SERVICE as T,SERVER_GROUP_WRITER as N,OVERRIDE_REGISTRY as P,STAGE_ARTIFACT_SELECTOR_COMPONENT_REACT as I,TaskMonitor as z,ModalWizard as x,TetheredSelect as M,HelpField as R,withErrorBoundary as $,ArtifactTypePatterns as B,StageArtifactSelectorDelegate as F,StageConfigField as L,CheckboxInput as O,ServerGroupWarningMessageService as U,ServerGroupReader as q,DeploymentStrategyRegistry as H}from"@spinnaker/core";import V from"@uirouter/angularjs";import _ from"angular-ui-bootstrap";import j,{isEqual as W,clone as Z,has as K,flatten as J,keys as Y,chain as X,find as Q,intersection as ee,xor as te,extend as ne,some as ae,uniqWith as re,defaults as ie,filter as se,isEmpty as oe}from"lodash";import{getAllTargetGroups as le,applyHealthCheckInfoToTargetGroups as ce,VpcReader as de}from"@spinnaker/amazon";import*as pe from"react";import ue from"react";import{UISrefActive as me,UISref as ge}from"@uirouter/react";import{DockerImageReader as ve}from"@spinnaker/docker";import{Alert as he}from"react-bootstrap";import{react2angular as fe}from"react2angular";import{$log as ye}from"ngimport";const be={bindings:{action:"&",isValid:"&",cancel:"&",account:"=?",verification:"=?"},template:'\n <div class="modal-footer">\n <user-verification account="$ctrl.account" verification="$ctrl.verification"></user-verification>\n <button type="submit" ng-click="$ctrl.action()" style="display:none"></button> \x3c!-- Allows form submission via enter keypress--\x3e\n <button class="btn btn-default" ng-click="$ctrl.cancel()">Cancel</button>\n <button type="submit"\n class="btn btn-primary"\n ng-click="$ctrl.action()"\n ng-disabled="!$ctrl.isValid()">\n Submit\n </button>\n </div>\n ',controller:()=>{}},Se="spinnaker.ecs.footer";t(Se,[]).component("ecsFooter",be);const ke="spinnaker.ecs.common";t(ke,[Se]);const Ce={"ecs.loadBalancer.targetGroup":"<p>A <em>target group</em> is attached to an application / network load balancer and is a target for load balancer traffic.</p> <p> You need to create both the application load balancer and target groups prior to being able to use them in your pipeline.</p>","ecs.serverGroup.clusterName":"<p>The name of the ECS cluster (group of underlying EC2 hosts) onto which your application will be deployed.</p><p>Note that suggestions here are dependent on the selected account and region combination.</p>","ecs.stage.findImageByTags.labelOrSha":"<p>As of now, only Amazon's ECR is supported as a source docker repository.</p>","ecs.serverGroup.stack":"<p>An environment variable available within your container, and on which you should base your application configuration at runtime.</p> <p>Typical values for this parameter are <i>staging</i>, <i>prod</i>, etc. Keep this parameter short!</p>","ecs.serverGroup.detail":"<p>An environment variable available within your container, and on which you should base your application configuration at runtime.</p> <p>Typical values for this parameter are <i>app</i>, <i>worker</i>, <i>migrator</i>, etc. Keep this parameter short!</p>","ecs.capacity.overwrite":"<p>Checking this box will have the previous server group's capacity overwrite the new <i>min</i>, <i>max</i> and <i>desired capacity</i> parameters if a previous server group exists.</p>","ecs.capacity.desired":"<p>The starting number of containers, before any autoscaling happens.</p>","ecs.capacity.minimum":"<p>The minimum number of containers you can reach as a result of autoscaling.</p> <p>Typically, this represents the bare minimum you can afford to run without impacting your capacity to meet your SLA (Service Level Agreement) objectives</p>","ecs.capacity.maximum":"<p>The maximal number of containers you can reach as a result of autoscaling.</p>","ecs.capacity.reserved.computeUnits":"<p>The assured minimal amount of computing capacity your container will be able to use. 1024 units are equal to 1 AWS virtual CPU</p> <p>If other containers on your underlying host are not using their reserved compute capacity, this container will be able to use it.</p>","ecs.capacity.reserved.memory":"<p>The maximal amount of memory that your container can use, in megabytes. Exceeding this amount may result in termination of your container.</p><p>1024 mb = 1 gb</p>","ecs.loadbalancing.targetPort":"<p>The port on which your application is listening for incoming traffic</p>","ecs.iamrole":"<p>The IAM role that your container (task, in AWS wording) will inherit. </p><p>Define a role only if your application needs to access AWS APIs</p>","ecs.dockerimage":"Docker image for your container, such as nginx:latest","ecs.dockerimagecredentials":"<p>The AWS Secrets Manager secret that contains private registry credentials.</p><p>Define credentials only for private registries other than Amazon ECR.</p>","ecs.placementConstraints":'<p>Rules for task placement. See <a href="https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-placement-constraints.html" target="_blank">AWS documentation</a> for more details. </p>',"ecs.placementConstraintType":"<p>To ensure that each task in a particular group is running on a different container instance, use distinctInstance. To restrict the selection to a group of valid candidates, use memberOf. </p>","ecs.placementConstraintExpression":'<p>A cluster query language expression to apply to memberOf constraints. See <a href="https://docs.aws.amazon.com/AmazonECS/latest/developerguide/cluster-query-language.html" target="_blank">AWS documentation</a> for more details.</p>',"ecs.placementStrategy":'<p>The strategy the container scheduler will be using. See <a href="http://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-placement-strategies.html" target="_blank">AWS documentation</a> for more details. </p><p>You should at least balance across availability zones</p><p>Custom placement strategies have not been implemented yet.</p>',"ecs.platformVersion":"<p>Defaults to the latest platform version.</p>","ecs.enableDeploymentCircuitBreaker":"<p>Enable circuit breaker for the ECS service.</p>","ecs.capacity.copySourceScalingPoliciesAndActions":"<p>Copy Application Autoscaling policies and their associated alarms from the previous ECS service.</p>","ecs.launchtype":"<p>Launch service tasks on your own EC2 instances or on Fargate.</p>","ecs.healthgraceperiod":"<p>How long a container will be kept alive despite the load balancer health checks, in seconds.</p>","ecs.publicip":"<p>Assign a public IP address to each task.</p>","ecs.networkMode":"<p>awsvpc is the only networking mode that allows you to use Elastic Network Interfaces (ENI). The default value converts to Bridge on Linux, and NAT on Windows.</p>","ecs.subnet":"<p>The subnet group(s) on which your server group will be deployed. All subnet groups selected must exist within the same VPC.</p>","ecs.securityGroups":"<p>The security group(s) name(s) your containers are deployed with.</p>","ecs.dockerLabels":'<p>Additional labels applied to your Docker container. This metadata can be used to identify your containers, or in conjunction with logging options. Maps directly to the <a href="https://docs.docker.com/engine/reference/commandline/run/#set-metadata-on-container--l---label---label-file"><b>--label</b> Docker flag</a>.</p> <p>Spinnaker will automatically add the spinnaker.servergroup, spinnaker.stack, spinnaker.detail labels for non-null values.</p>',"ecs.logDriver":'<p>The container\'s logging driver. This directly maps to the <a href="https://docs.docker.com/config/containers/logging/configure/#configure-the-default-logging-driver"><b>--log-driver</b> Docker flag.</a></p>',"ecs.logOptions":'<p>A map of log options. This directly maps with the <a href="https://docs.docker.com/config/containers/logging/log_tags/"><b>--log-opt</b> Docker flag </a></p>',"ecs.taskDefinition":'<p>The source of the ECS Task Definition. Task Definition contents can either be entered manually via input fields or from a selected JSON file artifact. Artifact file contents should be structured as an ECS "RegisterTaskDefinition" request.</p>',"ecs.taskDefinitionArtifact":"<p>The artifact containing the ECS Task Definition.</p>","ecs.containerMappings":"<p>The list of expected containers within the Task Definition and which container image they should use. Containers in the Task Definition which are not specified here will be registered as they appear in the artifact.</p>","ecs.containerMappingName":'<p>The name of the container. Name should match the <a href="https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_ContainerDefinition.html#ECS-Type-ContainerDefinition-name"><b>containerDefinition.name</b></a> field as it appears in the Task Definition.</p>',"ecs.containerMappingImage":"<p>The container image the named container should run.</p>","ecs.targetGroupMappings":"<p>The list of target groups through which the ECS service will receive load balancer traffic. Each target group is mapped to a container name and port within the Task Definition to specify which container should be registered to the target group.</p>","ecs.loadBalancedContainer":"<p>The container in the Task Definition that should receive traffic from the load balancer. Required if a load balancer target group has been specified.</p>","ecs.tags":"<p>The tags to apply to the task definition and the service","ecs.environmentVariables":"<p>The environment variable(s) your container are deployed with. SERVER_GROUP, CLOUD_STACK and CLOUD_DETAIL environment variables are used during deployment to identify the task and cannot be set here.</p>","ecs.serviceDiscovery":"<p>The AWS Cloud Map service discovery registries to assign to this service</p>","ecs.serviceDiscoveryRegistry":"<p>The AWS Cloud Map service to use for service discovery registration</p>","ecs.serviceDiscoveryContainerPort":"<p>The port to be used for your service discovery service. Required only for services using bridge or host network mode, and for services using awsvpc network mode and a type SRV DNS record","ecs.serviceDiscoveryContainerName":"<p>The container name value, already specified in the task definition, to be used for your service discovery service.</p>","ecs.computeOptions":'<p>Specify either a <a href="https://docs.aws.amazon.com/AmazonECS/latest/developerguide/launch_types.html" target="_blank">launch type</a> (default) or <a href="https://docs.aws.amazon.com/AmazonECS/latest/developerguide/cluster-capacity-providers.html" target="_blank">capacity providers</a> for running your ECS service.</p>',"ecs.capacityProviderStrategy":'<p>A capacity provider strategy gives you control over how your tasks use one or more capacity providers. See <a href="https://docs.aws.amazon.com/AmazonECS/latest/developerguide/cluster-capacity-providers.html#capacity-providers-concepts" target="_blank">AWS documentation</a> for more details. </p>',"ecs.capacityProviderName":"<p>The short name of the capacity provider.</p>","ecs.capacityProviderBase":"<p>Designates how many tasks, at a minimum, to run on the specified capacity provider. Only one capacity provider in a capacity provider strategy can have a <em>base</em> defined.</p>","ecs.capacityProviderWeight":"<p>Designates the relative percentage of the total number of tasks launched that should use the specified capacity provider.</p>","ecs.evaluateExpression":'<p>Whether to evaluate <a href="https://spinnaker.io/guides/user/pipeline/expressions/" target="_blank"><b>pipeline expressions</b></a> within the task definition artifact in this stage. Checking this box let\'s you evaluate your task definition artifact coming from external sources.(e.g. GitHub) </p>'};Object.keys(Ce).forEach((e=>n.register(e,Ce[e])));const we=a.providers.ecs||{defaults:{}};we&&(we.resetToOriginal=a.resetProvider("ecs"));const Ee="spinnaker.ecs.ecsCluster.read.service";t(Ee,[]).service("ecsClusterReader",class{listClusters(){return r("/ecs/ecsClusters").get()}describeClusters(e,t){return null!=e&&null!=t?r("/ecs/ecsClusterDescriptions").path(e).path(t).get():{}}});const De="spinnaker.ecs.iamRole.read.service";t(De,[]).service("iamRoleReader",class{listRoles(e){return r("/roles").path(e).get()}});const Ge="spinnaker.ecs.instance.details.controller";t(Ge,[V,_]).controller("ecsInstanceDetailsCtrl",["$scope","$state","$uibModal","instance","app","moniker","environment","$q","overrides",function(e,t,n,r,d,p,u,m,g){e.detailsTemplateUrl=i.getValue("ecs","instance.detailsTemplateUrl"),e.state={loading:!0,standalone:d.isStandalone,instancePort:j.get(d,"attributes.instancePort")||a.defaultInstancePort||80},e.application=d,e.moniker=p,e.environment=u;const v={cloudProvider:"ecs"};function h(){const t={};let n,a,i,s,c,p;return d.serverGroups?(d.serverGroups.data.some((function(e){return e.instances.some((function(o){if(o.id===r.instanceId)return n=o,a=e.loadBalancers,i=e.targetGroup,s=e.account,c=e.region,p=e.vpcId,t.serverGroup=e.name,t.vpcId=e.vpcId,!0}))})),n||(d.loadBalancers.data.some((function(e){return e.instances.some((function(t){if(t.id===r.instanceId)return n=t,a=[e.name],s=e.account,c=e.region,p=e.vpcId,!0}))||e.targetGroup.some((function(t){return t.instances.some((function(a){if(a.id===r.instanceId)return n=a,t=t.name,s=e.account,c=e.region,p=e.vpcId,!0}))}))})),n||d.loadBalancers.data.some((function(e){return e.serverGroups.some((function(t){return!!t.isDisabled&&t.instances.some((function(t){if(t.id===r.instanceId)return n=t,a=[e.name],s=e.account,c=e.region,p=e.vpcId,!0}))}))||e.targetGroup.some((function(t){t.serverGroups.some((function(t){return!!t.isDisabled&&t.instances.some((function(t){if(t.id===r.instanceId)return n=t,a=[e.name],s=e.account,c=e.region,p=e.vpcId,!0}))}))}))})))):(n={},a=[],i=[],s=r.account,c=r.region),n&&s&&c?(n.account=s,t.account=s,t.region=c,o.addExtraDataToLatest("instances",t),l.getInstanceDetails(s,c,r.instanceId).then((t=>{if(!e.$$destroyed){if(e.state.loading=!1,function(t,n){d.isStandalone&&(t.health=n.health),t.health=t.health||[];const a=t.health.filter((function(e){return"Ecs"!==e.type||"Unknown"!==e.state})),r=le(d.loadBalancers.data);ce(a,r,t.account),n.health&&a.forEach((function(e){const t=n.health.filter((function(t){return t.type===e.type}));t.length&&j.defaults(e,t[0])})),e.healthMetrics=a}(n,t),e.instance=j.defaults(t,n),e.instance.account=s,e.instance.region=c,e.instance.vpcId=p,e.instance.loadBalancers=a,e.instance.targetGroup=i,e.instance.networkInterfaces){const t=e.instance.networkInterfaces.filter((e=>!1===e.attachment.deleteOnTermination));t.length&&(e.instance.permanentIps=t.map((e=>e.privateIpAddress)))}e.baseIpAddress=t.publicDnsName||t.privateIpAddress,g.instanceDetailsLoaded&&g.instanceDetailsLoaded()}}),f)):(n||(e.instanceIdNotFound=r.instanceId,e.state.loading=!1),m.when(null))}function f(){e.$$destroyed||(d.isStandalone?(e.state.loading=!1,e.instanceIdNotFound=r.instanceId,e.state.notFoundStandalone=!0,o.removeLastItem("instances")):t.go("^",{allowModalToStayOpen:!0},{location:"replace"}))}this.canRegisterWithDiscovery=function(){const t=(e.instance.health||[]).filter((function(e){return"Discovery"===e.type}));return!!t.length&&"OutOfService"===t[0].state},this.terminateInstance=function(){const n=e.instance,a={application:d,title:"Terminating "+n.instanceId,onTaskComplete:function(){t.includes("**.instanceDetails",{instanceId:n.instanceId})&&t.go("^")}};s.confirm({header:"Really terminate "+n.instanceId+"?",buttonText:"Terminate "+n.instanceId,account:n.account,taskMonitorConfig:a,submitMethod:function(){return c.terminateInstance(n,d,v)}})},this.terminateInstanceAndShrinkServerGroup=function(){const n=e.instance,a={application:d,title:"Terminating "+n.instanceId+" and shrinking server group",onTaskComplete:function(){t.includes("**.instanceDetails",{instanceId:n.instanceId})&&t.go("^")}};s.confirm({header:"Really terminate "+n.instanceId+" and shrink "+n.serverGroup+"?",buttonText:"Terminate "+n.instanceId+" and shrink "+n.serverGroup,account:n.account,taskMonitorConfig:a,submitMethod:function(){return c.terminateInstanceAndShrinkServerGroup(n,d,v)}})},this.enableInstanceInDiscovery=function(){const t=e.instance,n={application:d,title:"Enabling "+t.instanceId+" in discovery"};s.confirm({header:"Really enable "+t.instanceId+" in discovery?",buttonText:"Enable "+t.instanceId,account:t.account,taskMonitorConfig:n,submitMethod:function(){return c.enableInstanceInDiscovery(t,d,v)}})},this.disableInstanceInDiscovery=function(){const t=e.instance,n={application:d,title:"Disabling "+t.instanceId+" in discovery"};s.confirm({header:"Really disable "+t.instanceId+" in discovery?",buttonText:"Disable "+t.instanceId,account:t.account,taskMonitorConfig:n,submitMethod:function(){return c.disableInstanceInDiscovery(t,d,v)}})},this.hasHealthState=function(t,n){return(e.instance.health||[]).some((function(e){return e.type===t&&e.state===n}))};(d.isStandalone?h():m.all([d.serverGroups.ready(),d.loadBalancers.ready()]).then(h)).then((()=>{e.$$destroyed||d.isStandalone||d.serverGroups.onRefresh(e,h)})),e.account=r.account}]);class Ae extends ue.Component{render(){const{targetGroup:e,loadBalancer:t,showServerGroups:n}=this.props,a={loadBalancerName:t.name,region:e.region,accountId:e.account,name:e.targetGroupName,vpcId:e.vpcId,provider:e.cloudProvider},r={up:void 0,down:void 0,starting:void 0,succeeded:void 0,failed:void 0,unknown:void 0,outOfService:void 0};return ue.createElement("div",{className:"target-group-container container-fluid no-padding"},ue.createElement(me,{class:"active"},ue.createElement(ge,{to:".ecsTargetGroupDetails",params:a},ue.createElement("div",{className:"clickable clickable-row row no-margin-y target-group-header"},ue.createElement("div",{className:"col-md-8 target-group-title"},e.targetGroupName)))),n&&e.serverGroups.map((t=>ue.createElement(d,{key:t,account:e.account,region:e.region,serverGroup:{account:e.account,cloudProvider:e.cloudProvider,cluster:t,instanceCounts:r,instances:e.instances,name:t,type:e.type,region:e.region},showInstances:!1}))))}}class Te extends ue.Component{shouldComponentUpdate(e){return e.showInstances!==this.props.showInstances||e.showServerGroups!==this.props.showServerGroups||e.loadBalancer!==this.props.loadBalancer||(()=>!W((e.serverGroups||[]).map((e=>e.name)),(this.props.serverGroups||[]).map((e=>e.name))))()||(()=>!W((e.loadBalancer.targetGroups||[]).map((e=>e.targetGroupName)),(this.props.loadBalancer.targetGroups||[]).map((e=>e.targetGroupName))))()}render(){const{loadBalancer:e,showInstances:t,showServerGroups:n}=this.props,a=e.targetGroups.map((a=>ue.createElement(Ae,{key:a.targetGroupName,loadBalancer:e,targetGroup:a,showInstances:t,showServerGroups:n})));return ue.createElement("div",{className:"cluster-container"},a)}}class Ne extends ue.Component{constructor(e){super(e)}getTargetGroupNameFromArn(e){const t=e.split("/");return t.length<0?e:t[1]}render(){const{port:e,protocol:t,defaultActions:n}=this.props.listener;return ue.createElement("div",null,ue.createElement("h4",null,t,":",e),ue.createElement("div",{style:{paddingLeft:10}},ue.createElement("i",null,"default actions"),ue.createElement("ul",null,n.map(((e,t)=>"forward"==e.type?ue.createElement("li",{key:t},"→",ue.createElement("i",{className:"fa fa-fw fa-crosshairs icon","aria-hidden":"true"}),ue.createElement("span",null,e.targetGroupArn||e.forwardConfig.targetGroups.map((e=>this.getTargetGroupNameFromArn(e.targetGroupArn))))):ue.createElement("li",{key:t},e.type,":"," ",e.redirectConfig.statusCode||e.fixedResponseConfig.statusCode||e.authenticateOidcConfig.clientId||e.authenticateCognitoActionConfig.userPoolDomain))))))}}class Pe extends ue.Component{constructor(e){super(e),this.state={loading:!0,loadBalancer:void 0,refreshListenerUnsubscribe:()=>{}},e.app.getDataSource("loadBalancers").ready().then((()=>this.extractLoadBalancer()))}componentWillUnmount(){this.state.refreshListenerUnsubscribe()}extractLoadBalancer(){const{name:e,region:t}=this.props.loadBalancer,n=this.props.app.getDataSource("loadBalancers").data.find((n=>n.name===e&&n.account===this.props.loadBalancer.accountId&&n.region===t));this.setState({loading:!1,loadBalancer:n}),this.state.refreshListenerUnsubscribe(),n?this.setState({refreshListenerUnsubscribe:this.props.app.getDataSource("loadBalancers").onRefresh(null,(()=>this.extractLoadBalancer()))}):this.setState({refreshListenerUnsubscribe:()=>{}})}render(){const e=this.props.loadBalancer.name,{loadBalancer:t,loading:n}=this.state,{accountId:a}=this.props,r=ue.createElement("div",{className:"close-button"},ue.createElement(ge,{to:"^"},ue.createElement("span",{className:"glyphicon glyphicon-remove"})));return ue.createElement("div",{className:"details-panel"},n&&ue.createElement("div",{className:"header"},r,ue.createElement("div",{className:"horizontal center middle"},ue.createElement(p,{size:"small"}))),!n&&ue.createElement("div",{className:"header"},r,ue.createElement("div",{className:"header-text horizontal middle"},ue.createElement("i",{className:"fa icon-sitemap"}),ue.createElement("h3",{className:"horizontal middle space-between flex-1"},e))),!n&&!t&&ue.createElement("div",{className:"content"},ue.createElement("div",{className:"content-section"},ue.createElement("div",{className:"content-body text-center"},ue.createElement("h3",null,"Load balancer not found.")))),!n&&t&&ue.createElement("div",{className:"content"},ue.createElement(u,{heading:"Load Balancer Details",defaultExpanded:!0},ue.createElement("dl",{className:"dl-horizontal dl-narrow"},ue.createElement("dt",null,"Created"),ue.createElement("dd",null,m(t.createdTime)),ue.createElement("dt",null,"In"),ue.createElement("dd",null,ue.createElement(g,{account:a}),ue.createElement("br",null),t.region),ue.createElement("dt",null,"VPC"),ue.createElement("dd",null,t.vpcId),ue.createElement("dt",null,"Type"),ue.createElement("dd",null,t.loadBalancerType),ue.createElement("dt",null,"IP Type"),ue.createElement("dd",null,t.ipAddressType)),ue.createElement("dl",{className:"horizontal-when-filters-collapsed"},ue.createElement("dt",null,"Availability Zones"),ue.createElement("dd",null,ue.createElement("ul",null,t.availabilityZones.map((e=>ue.createElement("li",{key:e},e)))))),ue.createElement("dl",{className:"horizontal-when-filters-collapsed"},ue.createElement("dt",null,"Target Groups"),ue.createElement("dd",null,ue.createElement("ul",null,t.targetGroups.map((e=>ue.createElement("li",{key:e.targetGroupName},ue.createElement(me,{class:"active"},ue.createElement(ge,{to:"^.ecsTargetGroupDetails",params:{loadBalancerName:t.name,region:t.region,accountId:t.account,name:e.targetGroupName,vpcId:e.vpcId,provider:t.cloudProvider}},ue.createElement("a",null,e.targetGroupName))))))))),ue.createElement("dl",{className:"horizontal-when-filters-collapsed"},ue.createElement("dt",null,"DNS Name"),ue.createElement("dd",null,ue.createElement("a",{target:"_blank",href:"http://"+t.dnsname},t.dnsname)))),ue.createElement(u,{heading:"Status",defaultExpanded:!1},ue.createElement("span",null,"Select a target group to check the instance health status from the view of its server groups.")),ue.createElement(u,{heading:"Listeners",defaultExpanded:!1},t.listeners?t.listeners.map(((e,t)=>ue.createElement("div",{key:t},ue.createElement("span",null,ue.createElement(Ne,{listener:e}))))):ue.createElement("li",null,"No listeners provided.")),ue.createElement(u,{heading:"Firewalls",defaultExpanded:!1},ue.createElement("ul",null,t.securityGroups?t.securityGroups.map((e=>ue.createElement("li",{key:e},e))):ue.createElement("li",null,"No security groups provided."))),ue.createElement(u,{heading:"Subnets",defaultExpanded:!1},ue.createElement("ul",null,t.subnets.map((e=>ue.createElement("li",{key:e},e)))))))}}class Ie extends ue.Component{constructor(e){super(e),this.state={loading:!0,targetGroup:void 0,loadBalancer:void 0,refreshListenerUnsubscribe:()=>{}},e.app.getDataSource("loadBalancers").ready().then((()=>this.extractTargetGroup()))}componentWillUnmount(){this.state.refreshListenerUnsubscribe()}extractTargetGroup(){const{loadBalancerName:e,region:t,targetGroupName:n}=this.props.targetGroup,a=this.props.app.getDataSource("loadBalancers").data.find((n=>n.name===e&&n.account===this.props.accountId&&n.region===t));if(this.setState({loadBalancer:a}),this.state.refreshListenerUnsubscribe(),a){const e=a.targetGroups.find((e=>e.targetGroupName===n));e||this.setState({loading:!1,targetGroup:null}),e&&(this.setState({loading:!1,targetGroup:e}),e?this.setState({refreshListenerUnsubscribe:this.props.app.getDataSource("loadBalancers").onRefresh(null,(()=>this.extractTargetGroup()))}):this.setState({refreshListenerUnsubscribe:()=>{}}))}else this.setState({loading:!1,targetGroup:null})}render(){const{name:e,accountId:t}=this.props,n=this.props.targetGroup.region,{targetGroup:a,loadBalancer:r,loading:i}=this.state,s=ue.createElement("div",{className:"close-button"},ue.createElement(ge,{to:"^"},ue.createElement("span",{className:"glyphicon glyphicon-remove"})));return ue.createElement("div",{className:"details-panel"},i&&ue.createElement("div",{className:"header"},s,ue.createElement("div",{className:"horizontal center middle"},ue.createElement(p,{size:"small"}))),!i&&ue.createElement("div",{className:"header"},ue.createElement("div",{className:"header-text horizontal middle"},ue.createElement("i",{className:"fa fa-crosshairs icon","aria-hidden":"true"}),ue.createElement("h3",{className:"horizontal middle space-between flex-1"},e))),!i&&!a&&ue.createElement("div",{className:"content"},ue.createElement("div",{className:"content-section"},ue.createElement("div",{className:"content-body text-center"},ue.createElement("h3",null,"Target group not found.")))),!i&&a&&ue.createElement("div",{className:"content"},ue.createElement(u,{heading:"Target Group Details",defaultExpanded:!0},ue.createElement("dl",{className:"dl-horizontal dl-narrow"},ue.createElement("dt",null,"In"),ue.createElement("dd",null,ue.createElement(g,{account:t}),ue.createElement("br",null),a.region),ue.createElement("dt",null,"VPC"),ue.createElement("dd",null,a.vpcId),ue.createElement("dt",null,"Protocol"),ue.createElement("dd",null,a.protocol),ue.createElement("dt",null,"Port"),ue.createElement("dd",null,a.port),ue.createElement("dt",null,"Target Type"),ue.createElement("dd",null,a.targetType.toUpperCase())),ue.createElement("dl",{className:"horizontal-when-filters-collapsed"},ue.createElement("dt",null,"Load Balancers"),ue.createElement("dd",null,ue.createElement("ul",{className:"collapse-margin-on-filter-collapse"},a.loadBalancerNames?a.loadBalancerNames.map(((e,t)=>ue.createElement("li",{key:t},e))):ue.createElement("li",null,"No load balncers provided.")))),ue.createElement("dl",{className:"horizontal-when-filters-collapsed"},ue.createElement("dt",null,"Load Balancer DNS Name"),ue.createElement("dd",null,ue.createElement("a",{target:"_blank",href:"http://"+r.dnsname},r.dnsname))),ue.createElement("dl",{className:"horizontal-when-filters-collapsed"},ue.createElement("dt",null,"Server Groups"),ue.createElement("dd",null,ue.createElement("ul",{className:"collapse-margin-on-filter-collapse"},a.serverGroups.map(((e,a)=>ue.createElement("li",{key:a},ue.createElement(me,{class:"active"},ue.createElement(ge,{to:"^.serverGroup",params:{region:n,accountId:t,serverGroup:e,provider:"ecs"}},ue.createElement("a",null,e)))))))))),ue.createElement(u,{heading:"Health Checks",defaultExpanded:!1},ue.createElement("dl",{className:"horizontal-when-filters-collapsed"},ue.createElement("dt",null,"Target"),ue.createElement("dd",null,a.healthCheckProtocol,":",a.healthCheckPort,a.healthCheckPath),ue.createElement("dt",null,"Timeout"),ue.createElement("dd",null,a.healthCheckTimeoutSeconds," seconds"),ue.createElement("dt",null,"Interval"),ue.createElement("dd",null,a.healthCheckIntervalSeconds," seconds"),ue.createElement("dt",null,"Healthy Threshold"),ue.createElement("dd",null,a.healthyThresholdCount),ue.createElement("dt",null,"Unhealthy Threshold"),ue.createElement("dd",null,a.unhealthyThresholdCount),ue.createElement("dt",null,"Matcher"),ue.createElement("dd",null,"HTTP Code(s): ",a&&a.matcher?a.matcher.httpCode:"None"))),ue.createElement(u,{heading:"Attributes",defaultExpanded:!1},ue.createElement("dl",null,ue.createElement("dt",null,"Deregistration Delay Timeout"),ue.createElement("dd",null,a.attributes["deregistration_delay.timeout_seconds"]||0," seconds"),ue.createElement("dt",null,"Stickiness Enabled"),ue.createElement("dd",null,a.attributes["stickiness.enabled"]||"N/A")))))}}class ze{constructor(e){this.$q=e}normalizeLoadBalancer(e){return e.targetGroups.forEach((t=>{if(t.region=e.region,t.account=e.account,t.cloudProvider=e.cloudProvider,e.targetGroupServices){const n=e.targetGroupServices;t.serverGroups=n[t.targetGroupArn]}})),this.$q.resolve(e)}}ze.$inject=["$q"];const xe="spinnaker.ecs.loadBalancer.targetGroup.states";t(xe,[v]).config(["applicationStateProvider",e=>{const t={name:"ecsTargetGroupDetails",url:"/ecsTargetGroupDetails/:provider/:accountId/:region/:vpcId/:loadBalancerName/:name",params:{vpcId:{value:null,squash:!0}},views:{"detail@../insight":{component:Ie,$type:"react"}},resolve:{accountId:["$stateParams",e=>e.accountId],name:["$stateParams",e=>e.name],provider:["$stateParams",e=>e.provider],targetGroup:["$stateParams",e=>({loadBalancerName:e.loadBalancerName,targetGroupName:e.name,accountId:e.accountId,region:e.region,vpcId:e.vpcId})]},data:{pageTitleDetails:{title:"Target Group Details",nameParam:"name",accountParam:"accountId",regionParam:"region"}}};e.addInsightDetailState(t)}]);const Me="spinnaker.ecs.metricAlarm.read.service";t(Me,[]).service("metricAlarmReader",class{listMetricAlarms(){return r("/ecs/cloudMetrics/alarms").get()}});const Re="spinnaker.ecs.pipeline.stage.ecs.destroyAsgStage";t(Re,[]).config((function(){h.pipeline.registerStage({provides:"destroyServerGroup",alias:"destroyAsg",cloudProvider:"ecs",templateUrl:"ecs/src/pipeline/stages/destroyAsg/destroyAsgStage.html",executionStepLabelUrl:"ecs/src/pipeline/stages/destroyAsg/destroyAsgStepLabel.html",accountExtractor:e=>[e.context.credentials],configAccountExtractor:e=>[e.credentials],validators:[{type:"targetImpedance",message:"This pipeline will attempt to destroy a server group without deploying a new version into the same cluster."},{type:"requiredField",fieldName:"cluster"},{type:"requiredField",fieldName:"target"},{type:"requiredField",fieldName:"regions"},{type:"requiredField",fieldName:"credentials",fieldLabel:"account"}]})})).controller("ecsDestroyAsgStageCtrl",["$scope",function(e){const t=e.stage;e.state={accounts:!1,regionsLoaded:!1},f.listAccounts("ecs").then((function(t){e.accounts=t,e.state.accounts=!0})),e.regions=["us-east-1","us-west-1","eu-west-1","us-west-2"],e.targets=y.TARGET_LIST,t.regions=t.regions||[],t.cloudProvider="ecs",!t.credentials&&e.application.defaultCredentials.ecs&&(t.credentials=e.application.defaultCredentials.ecs),!t.regions.length&&e.application.defaultRegions.ecs&&t.regions.push(e.application.defaultRegions.ecs),t.target||(t.target=e.targets[0].val)}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/pipeline/stages/destroyAsg/destroyAsgStage.html",'<div ng-controller="ecsDestroyAsgStageCtrl as destroyAsgStageCtrl" class="form-horizontal">\n <div ng-if="!pipeline.strategy">\n <account-region-cluster-selector application="application" component="stage" accounts="accounts">\n </account-region-cluster-selector>\n </div>\n <stage-config-field label="Target">\n <target-select model="stage" options="targets"></target-select>\n </stage-config-field>\n</div>\n')}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/pipeline/stages/destroyAsg/destroyAsgStepLabel.html",'<span class="task-label"> Destroy Server Group: {{step.context.serverGroupName}} ({{step.context.region}}) </span>\n')}]);const $e="spinnaker.ecs.pipeline.stage.disableAsgStage";t($e,[]).config((function(){h.pipeline.registerStage({provides:"disableServerGroup",alias:"disableAsg",cloudProvider:"ecs",templateUrl:"ecs/src/pipeline/stages/disableAsg/disableAsgStage.html",executionDetailsUrl:b.disableAsgExecutionDetails,executionStepLabelUrl:"ecs/src/pipeline/stages/disableAsg/disableAsgStepLabel.html",validators:[{type:"targetImpedance",message:"This pipeline will attempt to disable a server group without deploying a new version into the same cluster."},{type:"requiredField",fieldName:"cluster"},{type:"requiredField",fieldName:"target"},{type:"requiredField",fieldName:"regions"},{type:"requiredField",fieldName:"credentials",fieldLabel:"account"}]})})).controller("ecsDisableAsgStageCtrl",["$scope",function(e){const t=e.stage;e.state={accounts:!1,regionsLoaded:!1},f.listAccounts("ecs").then((function(t){e.accounts=t,e.state.accounts=!0})),e.targets=y.TARGET_LIST,t.regions=t.regions||[],t.cloudProvider="ecs",t.isNew&&e.application.attributes.platformHealthOnlyShowOverride&&e.application.attributes.platformHealthOnly&&(t.interestingHealthProviderNames=["Ecs"]),!t.credentials&&e.application.defaultCredentials.ecs&&(t.credentials=e.application.defaultCredentials.ecs),!t.regions.length&&e.application.defaultRegions.ecs&&t.regions.push(e.application.defaultRegions.ecs),t.target||(t.target=e.targets[0].val)}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/pipeline/stages/disableAsg/disableAsgStage.html",'<div ng-controller="ecsDisableAsgStageCtrl as disableAsgStageCtrl" class="form-horizontal">\n <div ng-if="!pipeline.strategy">\n <account-region-cluster-selector application="application" component="stage" accounts="accounts">\n </account-region-cluster-selector>\n </div>\n <stage-config-field label="Target">\n <target-select model="stage" options="targets"></target-select>\n </stage-config-field>\n <stage-platform-health-override application="application" stage="stage" platform-health-type="\'Ecs\'">\n </stage-platform-health-override>\n</div>\n')}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/pipeline/stages/disableAsg/disableAsgStepLabel.html",'<span class="task-label"> Disable Server Group: {{step.context.serverGroupName}} ({{step.context.region}}) </span>\n')}]);const Be="spinnaker.ecs.pipeline.stage.disableClusterStage";t(Be,[]).config((function(){h.pipeline.registerStage({provides:"disableCluster",cloudProvider:"ecs",templateUrl:"ecs/src/pipeline/stages/disableCluster/disableClusterStage.html",validators:[{type:"requiredField",fieldName:"cluster"},{type:"requiredField",fieldName:"remainingEnabledServerGroups",fieldLabel:"Keep [X] enabled Server Groups"},{type:"requiredField",fieldName:"regions"},{type:"requiredField",fieldName:"credentials",fieldLabel:"account"}]})})).controller("ecsDisableClusterStageCtrl",["$scope",function(e){const t=this,n=e.stage;e.state={accounts:!1,regionsLoaded:!1},f.listAccounts("ecs").then((function(t){e.accounts=t,e.state.accounts=!0})),t.reset=()=>{t.accountUpdated(),t.resetSelectedCluster()},n.regions=n.regions||[],n.cloudProvider="ecs",n.isNew&&e.application.attributes.platformHealthOnlyShowOverride&&e.application.attributes.platformHealthOnly&&(n.interestingHealthProviderNames=["Ecs"]),!n.credentials&&e.application.defaultCredentials.ecs&&(n.credentials=e.application.defaultCredentials.ecs),!n.regions.length&&e.application.defaultRegions.ecs&&n.regions.push(e.application.defaultRegions.ecs),void 0===n.remainingEnabledServerGroups&&(n.remainingEnabledServerGroups=1),t.pluralize=function(e,t){return 1===t?e:e+"s"},void 0===n.preferLargerOverNewer&&(n.preferLargerOverNewer="false"),n.preferLargerOverNewer=n.preferLargerOverNewer.toString()}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/pipeline/stages/disableCluster/disableClusterStage.html",'<div ng-controller="ecsDisableClusterStageCtrl as disableClusterStageCtrl" class="form-horizontal">\n <div ng-if="!pipeline.strategy">\n <account-region-cluster-selector application="application" component="stage" accounts="accounts">\n </account-region-cluster-selector>\n </div>\n <stage-config-field label="Disable Options">\n <div class="form-inline">\n Keep the\n <input\n type="number"\n min="0"\n required\n ng-model="stage.remainingEnabledServerGroups"\n class="form-control input-sm"\n style="width: 50px"\n />\n <select class="form-control input-sm" ng-model="stage.preferLargerOverNewer" style="width: 100px">\n <option value="true">largest</option>\n <option value="false">newest</option>\n </select>\n {{disableClusterStageCtrl.pluralize(\'server group\', stage.remainingEnabledServerGroups)}} enabled.\n </div>\n </stage-config-field>\n <stage-platform-health-override application="application" stage="stage" platform-health-type="\'Ecs\'">\n </stage-platform-health-override>\n</div>\n')}]);const Fe="spinnaker.ecs.pipeline.stage.enableAsgStage";t(Fe,[]).config((function(){h.pipeline.registerStage({provides:"enableServerGroup",alias:"enableAsg",cloudProvider:"ecs",templateUrl:"ecs/src/pipeline/stages/enableAsg/enableAsgStage.html",executionStepLabelUrl:"ecs/src/pipeline/stages/enableAsg/enableAsgStepLabel.html",validators:[{type:"requiredField",fieldName:"cluster"},{type:"requiredField",fieldName:"target"},{type:"requiredField",fieldName:"regions"},{type:"requiredField",fieldName:"credentials",fieldLabel:"account"}]})})).controller("ecsEnableAsgStageCtrl",["$scope",function(e){const t=this,n=e.stage;e.state={accounts:!1,regionsLoaded:!1},f.listAccounts("ecs").then((function(t){e.accounts=t,e.state.accounts=!0})),t.reset=()=>{t.accountUpdated(),t.resetSelectedCluster()},e.targets=y.TARGET_LIST,n.regions=n.regions||[],n.cloudProvider="ecs",n.isNew&&e.application.attributes.platformHealthOnlyShowOverride&&e.application.attributes.platformHealthOnly&&(n.interestingHealthProviderNames=["Ecs"]),!n.credentials&&e.application.defaultCredentials.ecs&&(n.credentials=e.application.defaultCredentials.ecs),!n.regions.length&&e.application.defaultRegions.ecs&&n.regions.push(e.application.defaultRegions.ecs),n.target||(n.target=e.targets[0].val),e.$watch("stage.credentials",e.accountUpdated)}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/pipeline/stages/enableAsg/enableAsgStage.html",'<div ng-controller="ecsEnableAsgStageCtrl as enableAsgStageCtrl" class="form-horizontal">\n <div ng-if="!pipeline.strategy">\n <account-region-cluster-selector application="application" component="stage" accounts="accounts">\n </account-region-cluster-selector>\n </div>\n <stage-config-field label="Target">\n <target-select model="stage" options="targets"></target-select>\n </stage-config-field>\n <stage-platform-health-override application="application" stage="stage" platform-health-type="\'Ecs\'">\n </stage-platform-health-override>\n</div>\n')}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/pipeline/stages/enableAsg/enableAsgStepLabel.html",'<span class="task-label"> Enable Server Group: {{step.context.serverGroupName}} ({{step.context.region}}) </span>\n')}]);const Le="spinnaker.ecs.pipeline.stage.findImageFromTagsStage";t(Le,[]).config((function(){h.pipeline.registerStage({provides:"findImageFromTags",cloudProvider:"ecs",templateUrl:"ecs/src/pipeline/stages/findImageFromTags/findImageFromTagsStage.html",executionDetailsUrl:"ecs/src/pipeline/stages/findImageFromTags/findImageFromTagsExecutionDetails.html",executionConfigSections:["findImageConfig","taskStatus"],validators:[{type:"requiredField",fieldName:"imageLabelOrSha"}]})})).controller("ecsFindImageFromTagsStageCtrl",["$scope",function(e){e.stage.cloudProvider=e.stage.cloudProvider||"ecs"}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/pipeline/stages/findImageFromTags/findImageFromTagsStage.html",'<div ng-controller="ecsFindImageFromTagsStageCtrl as findImageFromTagsCtrl" class="form-horizontal">\n <stage-config-field label="Full Docker Image path (label or SHA-256)">\n <input type="text" class="form-control input-sm" ng-model="stage.imageLabelOrSha" />\n </stage-config-field>\n</div>\n\n<div>\n <h5>Example value: <i>12345678901.dkr.ecr.us-west-2.amazonaws.com/continuous-delivery:latest</i></h5>\n</div>\n')}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/pipeline/stages/findImageFromTags/findImageFromTagsExecutionDetails.html",'<div ng-controller="BaseExecutionDetailsCtrl">\n <execution-details-section-nav sections="configSections"></execution-details-section-nav>\n <div class="step-section-details" ng-if="detailsSection === \'findImageConfig\'">\n <div class="row">\n <div class="col-md-12">\n <dl class="dl-narrow dl-horizontal">\n <dt if-multiple-providers>Provider</dt>\n <dd if-multiple-providers>ECS</dd>\n </dl>\n </div>\n </div>\n <stage-failure-message stage="stage" message="stage.failureMessage"></stage-failure-message>\n\n <div class="row" ng-if="stage.context.amiDetails">\n <div class="col-md-12">\n <div class="well alert alert-info">\n <h4>Results</h4>\n <dl ng-repeat="image in stage.context.amiDetails" class="dl-narrow dl-horizontal">\n <dt>Region</dt>\n <dd>{{image.region}}</dd>\n <dt>Image ID</dt>\n <dd>{{image.imageId}}</dd>\n <dt>Unique ID</dt>\n <dd>{{image.imageName}}</dd>\n </dl>\n </div>\n </div>\n </div>\n </div>\n\n <div class="step-section-details" ng-if="detailsSection === \'taskStatus\'">\n <div class="row">\n <execution-step-details item="stage"></execution-step-details>\n </div>\n </div>\n</div>\n')}]);const Oe="spinnaker.ecs.pipeline.stage.ecs.resizeAsgStage";t(Oe,[]).config((function(){h.pipeline.registerStage({provides:"resizeServerGroup",alias:"resizeAsg",cloudProvider:"ecs",templateUrl:"ecs/src/pipeline/stages/resizeAsg/resizeAsgStage.html",executionConfigSections:["resizeServerGroupConfig","taskStatus"],executionStepLabelUrl:"ecs/src/pipeline/stages/resizeAsg/resizeAsgStepLabel.html",accountExtractor:e=>[e.context.credentials],configAccountExtractor:e=>[e.credentials],validators:[{type:"targetImpedance",message:"This pipeline will attempt to resize a server group without deploying a new version into the same cluster."},{type:"requiredField",fieldName:"target"},{type:"requiredField",fieldName:"action"},{type:"requiredField",fieldName:"regions"},{type:"requiredField",fieldName:"cluster"},{type:"requiredField",fieldName:"credentials",fieldLabel:"account"}]})})).controller("ecsResizeAsgStageCtrl",["$scope",function(e){const t=e.stage;e.viewState={accountsLoaded:!1,regionsLoaded:!1},f.listAccounts("ecs").then((function(t){e.accounts=t,e.viewState.accountsLoaded=!0})),e.resizeTargets=y.TARGET_LIST,e.scaleActions=[{label:"Scale Up",val:"scale_up"},{label:"Scale Down",val:"scale_down"},{label:"Scale to Cluster Size",val:"scale_to_cluster"},{label:"Scale to Exact Size",val:"scale_exact"}],e.resizeTypes=[{label:"Percentage",val:"pct"},{label:"Incremental",val:"incr"}],t.capacity=t.capacity||{},t.regions=t.regions||[],t.target=t.target||e.resizeTargets[0].val,t.action=t.action||e.scaleActions[0].val,t.resizeType=t.resizeType||e.resizeTypes[0].val,void 0===t.targetHealthyDeployPercentage&&(t.targetHealthyDeployPercentage=100),t.action||"exact"!==t.resizeType||(t.action="scale_exact"),t.cloudProvider="ecs",t.isNew&&e.application.attributes.platformHealthOnlyShowOverride&&e.application.attributes.platformHealthOnly&&(t.interestingHealthProviderNames=["Ecs"]),!t.credentials&&e.application.defaultCredentials.ecs&&(t.credentials=e.application.defaultCredentials.ecs),!t.regions.length&&e.application.defaultRegions.ecs&&t.regions.push(e.application.defaultRegions.ecs),this.updateResizeType=function(){"scale_exact"===t.action?(t.resizeType="exact",delete t.scalePct,delete t.scaleNum):(t.capacity={},"pct"===t.resizeType?delete t.scaleNum:(t.resizeType="incr",delete t.scalePct,t.scaleNum=t.scaleNum||0))}}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/pipeline/stages/resizeAsg/resizeAsgStage.html",'<div ng-controller="ecsResizeAsgStageCtrl as resizeAsgStageCtrl">\n <div ng-if="!pipeline.strategy">\n <div ng-if="!viewState.accountsLoaded">\n <h4 class="text-center">\n <span us-spinner="{radius:20, width:6, length: 12}"></span>\n </h4>\n </div>\n <div ng-if="viewState.accountsLoaded">\n <account-region-cluster-selector application="application" component="stage" accounts="accounts">\n </account-region-cluster-selector>\n </div>\n </div>\n <stage-config-field label="Target">\n <target-select model="stage" options="resizeTargets"></target-select>\n </stage-config-field>\n <stage-config-field label="Action" help-key="pipeline.config.resizeAsg.action">\n <select\n class="form-control input-sm"\n required\n ng-model="stage.action"\n ng-change="resizeAsgStageCtrl.updateResizeType()"\n ng-options="a.val as a.label for a in scaleActions"\n >\n <option>Select an action...</option>\n </select>\n </stage-config-field>\n <div ng-if="stage.action !== \'scale_exact\'">\n <stage-config-field label="{{stage.action === \'scale_to_cluster\' ? \'Additional Capacity\' : \'Type\'}}">\n <select\n class="form-control input-sm"\n required\n ng-model="stage.resizeType"\n ng-change="resizeAsgStageCtrl.updateResizeType()"\n ng-options="t.val as t.label for t in resizeTypes"\n >\n <option>Select an action...</option>\n </select>\n </stage-config-field>\n <div ng-if="stage.resizeType === \'pct\'">\n <stage-config-field label="Resize Percentage">\n <input type="number" min="0" ng-model="stage.scalePct" class="form-control input-sm" style="width: 80px" />\n <div>\n <em class="subinput-note"\n >This is the percentage by which the target server group\'s capacity will be increased</em\n >\n </div>\n </stage-config-field>\n </div>\n <div ng-if="stage.resizeType === \'incr\'">\n <stage-config-field label="Resize-by Amount">\n <input type="number" min="0" ng-model="stage.scaleNum" class="form-control input-sm" style="width: 80px" />\n <div>\n <em class="subinput-note"\n >This is the exact amount by which the target server group\'s capacity will be increased</em\n >\n </div>\n </stage-config-field>\n </div>\n </div>\n <div ng-if="stage.action === \'scale_exact\'">\n <stage-config-field class="small">\n <div class="row">\n <div class="col-md-3">Min</div>\n <div class="col-md-3">Max</div>\n <div class="col-md-3">Desired</div>\n </div>\n </stage-config-field>\n <stage-config-field label="Match Capacity">\n <div class="row">\n <div class="col-md-3">\n <input type="number" ng-model="stage.capacity.min" class="form-control input-sm" />\n </div>\n <div class="col-md-3">\n <input type="number" ng-model="stage.capacity.max" class="form-control input-sm" />\n </div>\n <div class="col-md-3">\n <input type="number" ng-model="stage.capacity.desired" class="form-control input-sm" />\n </div>\n </div>\n </stage-config-field>\n <stage-config-field>\n <em class="subinput-note">This is the exact amount to which the target server group will be scaled</em>\n </stage-config-field>\n </div>\n <stage-platform-health-override application="application" stage="stage" platform-health-type="\'Ecs\'">\n </stage-platform-health-override>\n</div>\n')}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/pipeline/stages/resizeAsg/resizeAsgStepLabel.html",'<span class="task-label"> Resize Server Group: {{step.context.serverGroupName}} ({{step.context.region}}) </span>\n')}]);const Ue="spinnaker.ecs.pipeline.stage.scaleDownClusterStage";t(Ue,[]).config((function(){h.pipeline.registerStage({provides:"scaleDownCluster",cloudProvider:"ecs",templateUrl:"ecs/src/pipeline/stages/scaleDownCluster/scaleDownClusterStage.html",accountExtractor:e=>[e.context.credentials],configAccountExtractor:e=>[e.credentials],validators:[{type:"requiredField",fieldName:"cluster"},{type:"requiredField",fieldName:"remainingFullSizeServerGroups",fieldLabel:"Keep [X] full size Server Groups"},{type:"requiredField",fieldName:"regions"},{type:"requiredField",fieldName:"credentials",fieldLabel:"account"}],strategy:!0})})).controller("ecsScaleDownClusterStageCtrl",["$scope",function(e){const t=e.stage;e.state={accounts:!1,regionsLoaded:!1},f.listAccounts("ecs").then((function(t){e.accounts=t,e.state.accounts=!0})),t.regions=t.regions||[],t.cloudProvider="ecs",!t.credentials&&e.application.defaultCredentials.ecs&&(t.credentials=e.application.defaultCredentials.ecs),!t.regions.length&&e.application.defaultRegions.ecs&&t.regions.push(e.application.defaultRegions.ecs),void 0===t.remainingFullSizeServerGroups&&(t.remainingFullSizeServerGroups=1),void 0===t.allowScaleDownActive&&(t.allowScaleDownActive=!1),this.pluralize=function(e,t){return 1===t?e:e+"s"},void 0===t.preferLargerOverNewer&&(t.preferLargerOverNewer="false"),t.preferLargerOverNewer=t.preferLargerOverNewer.toString()}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/pipeline/stages/scaleDownCluster/scaleDownClusterStage.html",'<div ng-controller="ecsScaleDownClusterStageCtrl as scaleDownClusterStageCtrl" class="form-horizontal">\n <div ng-if="!pipeline.strategy">\n <account-region-cluster-selector application="application" component="stage" accounts="accounts">\n </account-region-cluster-selector>\n </div>\n <stage-config-field label="Scale Down Options">\n <div class="form-inline">\n <p>\n Keep the\n <input\n type="number"\n min="0"\n required\n ng-model="stage.remainingFullSizeServerGroups"\n class="form-control input-sm"\n style="width: 50px"\n />\n <select class="form-control input-sm" ng-model="stage.preferLargerOverNewer" style="width: 100px">\n <option value="true">largest</option>\n <option value="false">newest</option>\n </select>\n {{scaleDownClusterStageCtrl.pluralize(\'server group\', stage.remainingFullSizeServerGroups)}} at current size.\n </p>\n <p>The remaining server groups will be scaled down to zero instances.</p>\n </div>\n </stage-config-field>\n <div class="form-group">\n <div class="col-md-offset-3 col-md-6 checkbox">\n <label>\n <input type="checkbox" ng-model="stage.allowScaleDownActive" />\n Allow scale down of active server groups\n </label>\n </div>\n </div>\n</div>\n')}]);const qe="spinnaker.ecs.pipeline.stage.ecs.shrinkClusterStage";t(qe,[]).config((function(){h.pipeline.registerStage({provides:"shrinkCluster",cloudProvider:"ecs",templateUrl:"ecs/src/pipeline/stages/shrinkCluster/shrinkClusterStage.html",accountExtractor:e=>[e.context.credentials],configAccountExtractor:e=>[e.credentials],validators:[{type:"requiredField",fieldName:"cluster"},{type:"requiredField",fieldName:"shrinkToSize",fieldLabel:"shrink to [X] Server Groups"},{type:"requiredField",fieldName:"regions"},{type:"requiredField",fieldName:"credentials",fieldLabel:"account"}]})})).controller("ecsShrinkClusterStageCtrl",["$scope",function(e){const t=e.stage;e.state={accounts:!1,regionsLoaded:!1},f.listAccounts("ecs").then((function(t){e.accounts=t,e.state.accounts=!0})),t.regions=t.regions||[],t.cloudProvider="ecs",!t.credentials&&e.application.defaultCredentials.ecs&&(t.credentials=e.application.defaultCredentials.ecs),!t.regions.length&&e.application.defaultRegions.ecs&&t.regions.push(e.application.defaultRegions.ecs),void 0===t.shrinkToSize&&(t.shrinkToSize=1),void 0===t.allowDeleteActive&&(t.allowDeleteActive=!1),this.pluralize=function(e,t){return 1===t?e:e+"s"},void 0===t.retainLargerOverNewer&&(t.retainLargerOverNewer="false"),t.retainLargerOverNewer=t.retainLargerOverNewer.toString()}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/pipeline/stages/shrinkCluster/shrinkClusterStage.html",'<div ng-controller="ecsShrinkClusterStageCtrl as shrinkClusterStageCtrl" class="form-horizontal">\n <div ng-if="!pipeline.strategy">\n <account-region-cluster-selector application="application" component="stage" accounts="accounts">\n </account-region-cluster-selector>\n </div>\n <stage-config-field label="Shrink Options">\n <div class="form-inline">\n Shrink to\n <input\n type="number"\n min="0"\n required\n ng-model="stage.shrinkToSize"\n class="form-control input-sm"\n style="width: 50px"\n />\n {{shrinkClusterStageCtrl.pluralize(\'server group\', stage.shrinkToSize)}}, keeping the\n <select class="form-control input-sm" ng-model="stage.retainLargerOverNewer" style="width: 100px">\n <option value="true">largest</option>\n <option value="false">newest</option>\n </select>\n </div>\n </stage-config-field>\n <div class="form-group">\n <div class="col-md-offset-3 col-md-6 checkbox">\n <label>\n <input type="checkbox" ng-model="stage.allowDeleteActive" />\n Allow deletion of active server groups\n </label>\n </div>\n </div>\n <stage-platform-health-override application="application" stage="stage" platform-health-type="\'Ecs\'">\n </stage-platform-health-override>\n</div>\n')}]);const He="spinnaker.ecs.placementStrategyService.service";t(He,[]).service("placementStrategyService",class{getPredefinedStrategy(e){return"AZ Balanced Spread"===e?this.getAzBalancedSpreadStrategy():"AZ Balanced BinPack"===e||"AZ Balanced BinPack Memory"===e?this.getAzBalancedMemoryBinPackStrategy():"BinPack"===e||"BinPack Memory"===e?this.getBinPackMemoryStrategy():"AZ Balanced BinPack CPU"===e?this.getAzBalancedCpuBinPackStrategy():"BinPack CPU"===e?this.getBinPackCpuStrategy():"One Task Per Host"===e?this.getOneTaskPerHostStrategy():[]}getAzBalancedSpreadStrategy(){return[{type:"spread",field:"attribute:ecs.availability-zone"},{type:"spread",field:"instanceId"}]}getAzBalancedMemoryBinPackStrategy(){return[{type:"spread",field:"attribute:ecs.availability-zone"},{type:"binpack",field:"memory"}]}getBinPackMemoryStrategy(){return[{type:"binpack",field:"memory"}]}getAzBalancedCpuBinPackStrategy(){return[{type:"spread",field:"attribute:ecs.availability-zone"},{type:"binpack",field:"cpu"}]}getBinPackCpuStrategy(){return[{type:"binpack",field:"cpu"}]}getOneTaskPerHostStrategy(){return[{type:"spread",field:"instanceId"}]}});const Ve="spinnaker.ecs.secret.read.service";t(Ve,[]).service("secretReader",class{listSecrets(){return r("/ecs/secrets").get()}});const _e="spinnaker.ecs.securityGroup.details.controller";e.module(_e,[V,S,k]).controller("ecsSecurityGroupDetailsCtrl",["$scope","$state","resolvedSecurityGroup","app","securityGroupReader",function(t,n,a,r,s){this.application=r;const l=r,c=a;function d(){return s.getSecurityGroupDetails(l,c.accountId,c.provider,c.region,c.vpcId,c.name).then((function(e){return de.getVpcName(e.vpcId).then((t=>(e.vpcName=t,e)))})).then((function(n){if(t.state.loading=!1,!n||j.isEmpty(n))u();else{const a=s.getApplicationSecurityGroup(l,c.accountId,c.region,c.name);e.extend(c,a,n),t.securityGroup=c,t.ipRules=function(e){const t=j.groupBy(e.ipRangeRules,(e=>e.range.ip+e.range.cidr));return Object.keys(t).map((e=>({address:e,rules:p(t,e)}))).filter((e=>e.rules.length))}(c),t.securityGroupRules=function(e){const t=j.groupBy(e.securityGroupRules,(e=>e.securityGroup.id));return Object.keys(t).map((e=>({securityGroup:t[e][0].securityGroup,rules:p(t,e)}))).filter((e=>e.rules.length))}(c)}}),u)}function p(e,t){const n=[];return e[t].forEach((e=>{(e.portRanges||[]).forEach((t=>{("-1"===e.protocol||void 0!==t.startPort&&void 0!==t.endPort)&&n.push({startPort:t.startPort,endPort:t.endPort,protocol:e.protocol})}))})),n}function u(){t.$$destroyed||(r.isStandalone?(t.group=c.name,t.state.notFound=!0,t.state.loading=!1,o.removeLastItem("securityGroups")):n.go("^",{allowModalToStayOpen:!0},{location:"replace"}))}this.firewallLabel=C.get("Firewall"),t.detailsTemplateUrl=i.getValue("ecs","securityGroup.detailsTemplateUrl"),t.state={loading:!0,standalone:r.isStandalone},d().then((()=>{t.$$destroyed||r.isStandalone||r.securityGroups.onRefresh(t,d)})),r.isStandalone&&(r.securityGroups={refresh:d})}]);const je="spinnaker.ecs.securityGroup.reader";t(je,[]).service("ecsSecurityGroupReader",class{resolveIndexedSecurityGroup(e,t,n){return e[t.account][t.region][n]}});const We="spinnaker.ecs.securityGroup.transformer";t(We,[]).factory("ecsSecurityGroupTransformer",(function(){return{normalizeSecurityGroup:function(){}}}));const Ze="spinnaker.ecs.securityGroup";t(Ze,[je,We,_e]);class Ke{static listServiceDiscoveryRegistries(){return r("/ecs/serviceDiscoveryRegistries").get()}}class Je{constructor(e,t,n,a,r,i,s,o,l){this.$q=e,this.loadBalancerReader=t,this.serverGroupCommandRegistry=n,this.iamRoleReader=a,this.ecsClusterReader=r,this.metricAlarmReader=i,this.placementStrategyService=s,this.securityGroupReader=o,this.secretReader=l,this.launchTypes=["EC2","FARGATE"],this.networkModes=["bridge","host","awsvpc","none","default"]}configureUpdateCommand(e){e.backingData={launchTypes:Z(this.launchTypes),networkModes:Z(this.networkModes)}}configureCommand(e,t=""){this.applyOverrides("beforeConfiguration",e),e.toggleSuspendedProcess=(e,t)=>{e.suspendedProcesses=e.suspendedProcesses||[];const n=e.suspendedProcesses.indexOf(t);-1===n?e.suspendedProcesses.push(t):e.suspendedProcesses.splice(n,1)},e.processIsSuspended=(e,t)=>e.suspendedProcesses.includes(t),e.onStrategyChange=(e,t)=>{""!==t.key&&"custom"!==t.key&&(e.suspendedProcesses=(e.suspendedProcesses||[]).filter((e=>"AddToLoadBalancer"!==e)))},e.regionIsDeprecated=e=>K(e,"backingData.filtered.regions")&&e.backingData.filtered.regions.some((t=>t.name===e.region&&t.deprecated));const n=e.imageDescription?[this.grabImageAndTag(e.imageDescription.imageId)]:[];let a;return t&&n.push(t),a=n.length?this.$q.all(n.map((e=>ve.findImages({provider:"dockerRegistry",count:50,q:e})))).then((e=>J(e))):this.$q.when([]),this.$q.all({credentialsKeyedByAccount:f.getCredentialsKeyedByAccount("ecs"),loadBalancers:this.loadBalancerReader.listLoadBalancers("ecs"),subnets:G.listSubnetsByProvider("ecs"),iamRoles:this.iamRoleReader.listRoles("ecs"),ecsClusters:this.ecsClusterReader.listClusters(),capacityProviderDetails:this.ecsClusterReader.describeClusters(e.credentials,e.region),metricAlarms:this.metricAlarmReader.listMetricAlarms(),securityGroups:this.securityGroupReader.getAllSecurityGroups(),launchTypes:this.$q.when(Z(this.launchTypes)),networkModes:this.$q.when(Z(this.networkModes)),secrets:this.secretReader.listSecrets(),serviceDiscoveryRegistries:Ke.listServiceDiscoveryRegistries(),images:a}).then((t=>{t.accounts=Y(t.credentialsKeyedByAccount),t.filtered={},e.viewState.contextImages&&(t.images=t.images.concat(e.viewState.contextImages)),e.backingData=t,this.configureVpcId(e),this.configureAvailableIamRoles(e),this.configureAvailableSubnetTypes(e),this.configureAvailableSecurityGroups(e),this.configureAvailableEcsClusters(e),this.setCapacityProviderDetails(e),this.configureAvailableSecrets(e),this.configureAvailableServiceDiscoveryRegistries(e),this.configureAvailableImages(e),this.configureAvailableRegions(e),this.configureLoadBalancerOptions(e),this.applyOverrides("afterConfiguration",e),this.attachEventHandlers(e)}))}setCapacityProviderDetails(e){this.$q.all({capacityProviderDetails:this.ecsClusterReader.describeClusters(e.credentials,e.region)}).then((t=>{e.backingData.capacityProviderDetails=X(t.capacityProviderDetails).map((e=>this.mapCapacityProviderDetails(e))).value()})),null!=e.ecsClusterName&&e.ecsClusterName.length>0?this.configureAvailableCapacityProviders(e):(e.backingData.filtered.availableCapacityProviders=[],e.backingData.filtered.defaultCapacityProviderStrategy=[]),this.checkDirtyCapacityProviders(e)}configureAvailableCapacityProviders(e){e.backingData.filtered.availableCapacityProviders=X(e.backingData.capacityProviderDetails).filter({clusterName:e.ecsClusterName}).map((e=>e.capacityProviders)).flattenDeep().value(),e.backingData.filtered.defaultCapacityProviderStrategy=X(e.backingData.capacityProviderDetails).filter({clusterName:e.ecsClusterName}).map((e=>e.defaultCapacityProviderStrategy)).flattenDeep().value()}mapCapacityProviderDetails(e){return{capacityProviders:e.capacityProviders,clusterName:e.clusterName,defaultCapacityProviderStrategy:e.defaultCapacityProviderStrategy}}applyOverrides(e,t){this.serverGroupCommandRegistry.getCommandOverrides("ecs").forEach((n=>{n[e]&&n[e](t)}))}grabImageAndTag(e){return e.split("/").pop()}buildImageId(e){return e.fromContext?`${e.imageLabelOrSha}`:e.fromTrigger&&!e.tag?`${e.registry}/${e.repository} (Tag resolved at runtime)`:`${e.registry}/${e.repository}:${e.tag}`}mapImage(e){return void 0!==e.message?e:{repository:e.repository,tag:e.tag,imageId:this.buildImageId(e),registry:e.registry,fromContext:e.fromContext,fromTrigger:e.fromTrigger,account:e.account,imageLabelOrSha:e.imageLabelOrSha,stageId:e.stageId,message:e.message}}configureAvailableImages(e){e.backingData.filtered.images=e.backingData.images.map((e=>this.mapImage(e)))}configureAvailabilityZones(e){e.backingData.filtered.availabilityZones=Q(e.backingData.credentialsKeyedByAccount[e.credentials].regions,{name:e.region}).availabilityZones,e.availabilityZones=e.backingData.filtered.availabilityZones}configureAvailableSecurityGroups(e){if(null==e.subnetType&&(null==e.subnetTypes||0==e.subnetTypes.length))return void(e.backingData.filtered.securityGroups=[]);const t=X(e.backingData.subnets).filter({account:e.credentials,region:e.region,purpose:e.subnetTypes?e.subnetTypes[0]:e.subnetType}).compact().uniqBy("purpose").map("vpcId").value()[0];if(e.backingData.securityGroups[e.credentials]&&e.backingData.securityGroups[e.credentials].ecs&&e.backingData.securityGroups[e.credentials].ecs[e.region]){const n=e.backingData.securityGroups[e.credentials].ecs[e.region];e.backingData.filtered.securityGroupNames=X(n).filter({vpcId:t}).map("name").value()}}configureAvailableSubnetTypes(e){e.backingData.filtered.subnetTypes=X(e.backingData.subnets).filter({account:e.credentials,region:e.region}).compact().uniqBy("purpose").value().filter((function(e){return e.purpose&&e.purpose.length>0}))}configureAvailableEcsClusters(e){e.backingData.filtered.ecsClusters=X(e.backingData.ecsClusters).filter({account:e.credentials,region:e.region}).map("name").value()}configureAvailableSecrets(e){e.backingData.filtered.secrets=X(e.backingData.secrets).filter({account:e.credentials,region:e.region}).map("name").value()}buildServiceRegistryDisplayName(e){return`${e.name} (${e.id})`}mapServiceRegistry(e){return{account:e.account,region:e.region,name:e.name,id:e.id,arn:e.arn,displayName:this.buildServiceRegistryDisplayName(e)}}configureAvailableServiceDiscoveryRegistries(e){e.backingData.filtered.serviceDiscoveryRegistries=X(e.backingData.serviceDiscoveryRegistries).filter({account:e.credentials,region:e.region}).map((e=>this.mapServiceRegistry(e))).value()}configureAvailableRegions(e){const t=e.backingData.credentialsKeyedByAccount[e.credentials]||{regions:[]};e.backingData.filtered.regions=t.regions}configureAvailableIamRoles(e){e.backingData.filtered.iamRoles=X(e.backingData.iamRoles).filter({accountName:e.credentials}).map("name").value(),e.backingData.filtered.iamRoles.length>0&&e.backingData.filtered.iamRoles.splice(0,0,"None (No IAM role)")}configureSubnetPurposes(e){const t={dirty:{}},n=e.backingData.filtered;return null===e.region||(n.subnetPurposes=X(e.backingData.subnets).filter({account:e.credentials,region:e.region}).reject({target:"elb"}).reject({purpose:null}).uniqBy("purpose").value(),e.subnetTypes?t.dirty.subnetType=!e.subnetTypes.every((e=>X(n.subnetPurposes).some({purpose:e}).value())):X(n.subnetPurposes).some({purpose:e.subnetType}).value()||(t.dirty.subnetType=!0),t.dirty.subnetType&&(e.subnetTypes=null,e.subnetType=null)),t}getLoadBalancerMap(e){return X(e.backingData.loadBalancers).map("accounts").flattenDeep().filter({name:e.credentials}).map("regions").flattenDeep().filter({name:e.region}).map("loadBalancers").flattenDeep().value()}getLoadBalancerNames(e){return this.getLoadBalancerMap(e).filter((t=>(!t.loadBalancerType||"classic"===t.loadBalancerType)&&t.vpcId===e.vpcId)).map((e=>e.name)).sort()}getVpcLoadBalancerNames(e){return this.getLoadBalancerMap(e).filter((e=>(!e.loadBalancerType||"classic"===e.loadBalancerType)&&e.vpcId)).map((e=>e.name)).sort()}getTargetGroupNames(e){const t=this.getLoadBalancerMap(e).filter((e=>"classic"!==e.loadBalancerType));return J(t.map((e=>e.targetGroups))).sort()}configureLoadBalancerOptions(e){const t={dirty:{}},n=(e.loadBalancers||[]).concat(e.vpcLoadBalancers||[]),a=this.getLoadBalancerNames(e),r=this.getVpcLoadBalancerNames(e),i=this.getTargetGroupNames(e),s=e.targetGroupMappings.map((e=>e.targetGroup));if(n&&e.loadBalancers){const i=e.vpcId?a:a.concat(r),s=ee(i,n),o=te(s,n);e.loadBalancers=ee(a,s),e.vpcId?delete e.vpcLoadBalancers:e.vpcLoadBalancers=ee(r,s),o.length&&(t.dirty.loadBalancers=o)}if(s){const t=ee(i,s),n=te(t,s);n&&n.length>0?e.viewState.dirty.targetGroups=n:e.viewState.dirty&&e.viewState.dirty.targetGroups&&(e.viewState.dirty.targetGroups=[])}return e.backingData.filtered.loadBalancers=a,e.backingData.filtered.vpcLoadBalancers=r,e.backingData.filtered.targetGroups=i,t}refreshLoadBalancers(e,t){return this.loadBalancerReader.listLoadBalancers("ecs").then((n=>{e.backingData.loadBalancers=n,t||this.configureLoadBalancerOptions(e)}))}configureVpcId(e){const t={dirty:{}};if(null!=e.subnetType||null!=e.subnetTypes&&0!=e.subnetTypes.length)if(null!=e.subnetTypes&&e.subnetTypes.length>0)e.subnetTypes.forEach((function(t){const n=Q(e.backingData.subnets,{purpose:t,account:e.credentials,region:e.region});e.vpcId=n?n.vpcId:null}));else{const t=Q(e.backingData.subnets,{purpose:e.subnetType,account:e.credentials,region:e.region});e.vpcId=t?t.vpcId:null}else e.vpcId=null,t.dirty.vpcId=!0;return t}checkDirtyCapacityProviders(e){if(e.capacityProviderStrategy){const t=e.backingData.filtered.availableCapacityProviders,n=e.capacityProviderStrategy.map((e=>e.capacityProvider)),a=ee(t,n),r=te(a,n);if(r&&r.length>0?e.viewState.dirty.customCapacityProviders=r:e.viewState.dirty&&e.viewState.dirty.customCapacityProviders&&(e.viewState.dirty.customCapacityProviders=[]),e.useDefaultCapacityProviders){const t=e.backingData.filtered.defaultCapacityProviderStrategy.map((e=>e.capacityProvider)),a=ee(t,n),r=te(a,n);r&&r.length>0&&(e.viewState.dirty.defaulCapacityProviders=r)}}}attachEventHandlers(e){e.subnetChanged=e=>{const t=this.configureVpcId(e);return ne(t.dirty,this.configureLoadBalancerOptions(e).dirty),e.viewState.dirty=e.viewState.dirty||{},ne(e.viewState.dirty,t.dirty),t},e.regionChanged=e=>{const t={dirty:{}};return ne(t.dirty,this.configureSubnetPurposes(e).dirty),e.region&&(ne(t.dirty,e.subnetChanged(e).dirty),this.configureAvailabilityZones(e),this.configureAvailableEcsClusters(e),this.configureAvailableSubnetTypes(e),this.configureAvailableSecurityGroups(e),this.configureAvailableSecrets(e),this.configureAvailableServiceDiscoveryRegistries(e),this.setCapacityProviderDetails(e)),t},e.subnetTypeChanged=e=>(this.configureAvailableSecurityGroups(e),{dirty:{}}),e.clusterChanged=e=>{e.moniker=A.getMoniker(e.application,e.stack,e.freeFormDetails)},e.credentialsChanged=e=>{const t={dirty:{}},n=e.backingData;return e.credentials?(this.configureAvailableIamRoles(e),this.configureAvailableEcsClusters(e),this.configureAvailableSubnetTypes(e),this.configureAvailableSecurityGroups(e),this.configureAvailableSecrets(e),this.configureAvailableServiceDiscoveryRegistries(e),this.configureAvailableRegions(e),this.setCapacityProviderDetails(e),ae(n.filtered.regions,{name:e.region})?ne(t.dirty,e.regionChanged(e).dirty):(e.region=null,t.dirty.region=!0)):e.region=null,t},e.placementStrategyNameChanged=e=>(e.placementStrategySequence=this.placementStrategyService.getPredefinedStrategy(e.placementStrategyName),{dirty:{}}),this.applyOverrides("attachEventHandlers",e)}}Je.$inject=["$q","loadBalancerReader","serverGroupCommandRegistry","iamRoleReader","ecsClusterReader","metricAlarmReader","placementStrategyService","securityGroupReader","secretReader"];const Ye="spinnaker.ecs.serverGroup.configure.service";t(Ye,[w,S,E,D]).service("ecsServerGroupConfigurationService",Je);const Xe="spinnaker.ecs.serverGroupCommandBuilder.service";e.module(Xe,[T,Ye]).factory("ecsServerGroupCommandBuilder",["$q","instanceTypeService","ecsServerGroupConfigurationService",function(t,n,a){function r(e,t,n={}){if(n[e.refId])return[];n[e.refId]=!0;let a=[];return"findImageFromTags"===e.type&&a.push({fromContext:!0,imageLabelOrSha:e.imageLabelOrSha,stageId:e.refId}),e.requisiteStageRefIds.forEach((function(e){const i=t.find((t=>t.refId===e));i&&(a=a.concat(r(i,t,n)))})),a}function i(e){return e.filter((e=>"docker"===e.type)).map((e=>({fromTrigger:!0,repository:e.repository,account:e.account,organization:e.organization,registry:e.registry,tag:e.tag})))}function s(e,n){n=n||{};const a=f.getCredentialsKeyedByAccount("ecs"),r=n.account||e.defaultCredentials.ecs,i=n.region||e.defaultRegions.ecs,s=f.getAvailabilityZonesForAccountAndRegion("ecs",r,i);return t.all({preferredZones:s,credentialsKeyedByAccount:a}).then((function(t){const a=t.preferredZones;let s="None (No IAM role)";s=s.replace("{{application}}",e.name);const o={application:e.name,credentials:r,region:i,strategy:"",capacity:{min:1,max:1,desired:1},launchType:"EC2",healthCheckType:"EC2",selectedProvider:"ecs",iamRole:s,dockerImageCredentialsSecret:"None (No registry credentials)",availabilityZones:a,subnetType:"",securityGroupNames:[],healthCheckGracePeriodSeconds:"",placementConstraints:[],placementStrategyName:"",taskDefinitionArtifact:{},useTaskDefinitionArtifact:!1,placementStrategySequence:[],serviceDiscoveryAssociations:[],ecsClusterName:"",targetGroup:"",copySourceScalingPoliciesAndActions:!0,preferSourceCapacity:!0,useSourceCapacity:!0,enableDeploymentCircuitBreaker:!1,viewState:{useAllImageSelection:!1,useSimpleCapacity:!0,usePreferredZones:!0,mode:n.mode||"create",disableStrategySelection:!0,dirty:{}}};return e.attributes&&e.attributes.platformHealthOnlyShowOverride&&e.attributes.platformHealthOnly&&(o.interestingHealthProviderNames=["ecs"]),o}))}return{buildNewServerGroupCommand:s,buildServerGroupCommandFromExisting:function(e,t,n="clone"){return s(e,{account:t.account,region:t.region}).then((function(e){return e.credentials=t.account,e.app=t.moniker.app,e.stack=t.moniker.stack,e.region=t.region,e.ecsClusterName=t.ecsCluster,e.capacity=t.capacity,e.viewState.mode=n,e}))},buildNewServerGroupCommandForPipeline:function(e,n){let a=r(e,n.stages)||[];return a=a.concat(i(n.triggers)),t.when({viewState:{requiresTemplateSelection:!0,overrides:{viewState:{mode:"editPipeline",contextImages:a,pipeline:n,currentStage:e}}}})},buildServerGroupCommandFromPipeline:function(t,n,a,o){const l=j.cloneDeep(n),c=Object.keys(l.availabilityZones)[0];return s(t,{account:l.account,region:c}).then((function(t){const n=l.availabilityZones[c].join(",")===t.availabilityZones.join(",");let s=r(a,o.stages)||[];s=s.concat(i(o.triggers)),t.docker&&t.docker.image&&(t.docker.image=function(e,t){if(e.fromContext){const n=t.find((t=>e.stageId===t.stageId));return n?(e.cluster=n.cluster,e.pattern=n.pattern,e.repository=n.repository,e):null}if(e.fromTrigger)return t.find((t=>e.registry===t.registry&&e.repository===t.repository&&e.tag===t.tag))?e:null;return e}(t.docker.image,s));const d={instanceProfile:void 0,disableImageSelection:!0,useSimpleCapacity:l.capacity.min===l.capacity.max&&!0!==l.useSourceCapacity,usePreferredZones:n,mode:"editPipeline",submitButtonLabel:"Done",templatingEnabled:!0,existingPipelineCluster:!0,dirty:{},contextImages:s,pipeline:o,currentStage:a},p={region:c,credentials:l.account,availabilityZones:l.availabilityZones[c],viewState:d};return l.strategy=l.strategy||"",e.extend({},t,l,p)}))},buildUpdateServerGroupCommand:function(e){const t={type:"modifyAsg",asgs:[{asgName:e.name,region:e.region}],healthCheckType:e.asg.healthCheckType,credentials:e.account};return a.configureUpdateCommand(t),t}}}]);const Qe="spinnaker.ecs.cloneServerGroup.controller";t(Qe,[V,Ye,N,P,D,De,Ee,Ve,I]).controller("ecsCloneServerGroupCtrl",["$scope","$uibModalInstance","$q","$state","serverGroupWriter","overrideRegistry","ecsServerGroupConfigurationService","serverGroupCommandRegistry","serverGroupCommand","iamRoleReader","ecsClusterReader","secretReader","application","title",function(e,t,n,a,r,i,s,o,l,c,d,p,u,m){function g(){if(e.$$destroyed)return;const t=e.taskMonitor.task.execution.stages.find((e=>"cloneServerGroup"===e.type));if(t&&t.context["deploy.server.groups"]){const n=t.context["deploy.server.groups"][e.command.region];if(n){const t={serverGroup:n,accountId:e.command.credentials,region:e.command.region,provider:"ecs"};let r="^.^.^.clusters.serverGroup";a.includes("**.clusters.serverGroup")&&(r="^.serverGroup"),a.includes("**.clusters.cluster.serverGroup")&&(r="^.^.serverGroup"),a.includes("**.clusters")&&(r=".serverGroup"),a.go(r,t)}}}function v(){s.configureCommand(e.command).then((function(){e.state.loaded=!0,e.command.credentialsChanged(l),e.command.regionChanged(l),e.$watch("command.subnetType",h(e.command.subnetTypeChanged)),e.$watch("command.credentials",h(e.command.credentialsChanged)),e.$watch("command.region",h(e.command.regionChanged)),e.$watch("command.placementStrategyName",h(e.command.placementStrategyNameChanged)),e.$watch("command.stack",(()=>e.command.clusterChanged(e.command))),e.$watch("command.freeFormDetails",(()=>e.command.clusterChanged(e.command)))}))}function h(e){return function(){e(l)}}e.pages={templateSelection:i.getTemplate("ecs.serverGroup.templateSelection","ecs/src/serverGroup/configure/wizard/templateSelection/templateSelection.html"),basicSettings:i.getTemplate("ecs.serverGroup.basicSettings","ecs/src/serverGroup/configure/wizard/location/basicSettings.html"),container:i.getTemplate("ecs.serverGroup.container","ecs/src/serverGroup/configure/wizard/container/container.html"),horizontalScaling:i.getTemplate("ecs.serverGroup.horizontalScaling","ecs/src/serverGroup/configure/wizard/horizontalScaling/horizontalScaling.html"),networking:i.getTemplate("ecs.serverGroup.networking","ecs/src/serverGroup/configure/wizard/networking/networking.html"),logging:i.getTemplate("ecs.serverGroup.logging","ecs/src/serverGroup/configure/wizard/logging/logging.html"),serviceDiscovery:i.getTemplate("ecs.serverGroup.serviceDiscovery","ecs/src/serverGroup/configure/wizard/serviceDiscovery/serviceDiscovery.html"),advancedSettings:i.getTemplate("ecs.serverGroup.advancedSettings","ecs/src/serverGroup/configure/wizard/advancedSettings/advancedSettings.html"),taskDefinition:i.getTemplate("ecs.taskDefinition","ecs/src/serverGroup/configure/wizard/taskDefinition/taskDefinition.html")},e.title=m,e.applicationName=u.name,e.application=u,e.command=l,e.state={loaded:!1,requiresTemplateSelection:!!l.viewState.requiresTemplateSelection},this.templateSelectionText={copied:["account, region, ecs cluster, stack","capacity"],notCopied:["launch type, target group, network mode"]},e.command.viewState.disableStrategySelection||this.templateSelectionText.notCopied.push("the deployment strategy (if any) used to deploy the most recent server group"),e.taskMonitor=new z({application:u,title:"Creating your server group",modalInstance:t,onTaskComplete:function(){u.serverGroups.refresh(),u.serverGroups.onNextRefresh(e,g)}}),this.isValid=function(){return!0},this.showSubmitButton=function(){return x.allPagesVisited()},this.submit=function(){if("editPipeline"===e.command.viewState.mode||"createPipeline"===e.command.viewState.mode)return t.close(e.command);e.taskMonitor.submit((function(){return r.cloneServerGroup(e.command,u)}))},this.cancel=function(){t.dismiss()},e.state.requiresTemplateSelection?e.state.loaded=!0:v(),this.templateSelected=()=>{e.state.requiresTemplateSelection=!1,v()},e.notifyAngular=function(t,n){"pipeline"==t?e.command.viewState.pipeline=n:e.command[t]=n},e.configureCommand=function(t){return s.configureCommand(e.command,t)},e.capacityProviderState={useCapacityProviders:e.command.capacityProviderStrategy&&e.command.capacityProviderStrategy.length>0,updateComputeOption:function(t){"launchType"==t?e.command.capacityProviderStrategy=[]:"capacityProviders"==t&&(e.command.launchType="",e.command.capacityProviderStrategy=e.command.capacityProviderStrategy||[])}}}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/serverGroup/configure/wizard/templateSelection/templateSelection.html",'<deploy-initializer\n cloud-provider="ecs"\n command="command"\n application="application"\n parent-state="state"\n dismiss="ctrl.cancel()"\n template-selection-text="ctrl.templateSelectionText"\n on-template-selected="ctrl.templateSelected()"\n></deploy-initializer>\n')}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/serverGroup/configure/wizard/location/basicSettings.html",'<div class="container-fluid form-horizontal" ng-controller="ecsServerGroupBasicSettingsCtrl as basicSettingsCtrl">\n <ng-form name="basicSettings">\n <div class="form-group row" ng-if="command.regionIsDeprecated(command)">\n <div class="col-md-12 error-message">\n <div class="alert alert-danger">\n You are deploying into a deprecated region within the {{ command.credentials }} account!\n </div>\n </div>\n </div>\n <div class="form-group">\n <div class="col-md-3 sm-label-right">Account</div>\n <div class="col-md-7">\n <account-select-field\n read-only="command.viewState.readOnlyFields.credentials"\n component="command"\n field="credentials"\n accounts="command.backingData.accounts"\n provider="\'ecs\'"\n ></account-select-field>\n </div>\n </div>\n <region-select-field\n read-only="command.viewState.readOnlyFields.region"\n label-columns="3"\n component="command"\n field="region"\n account="command.credentials"\n provider="\'ecs\'"\n regions="command.backingData.filtered.regions"\n ></region-select-field>\n <div class="form-group">\n <div class="col-md-3 sm-label-right">\n ECS Cluster name <help-field key="ecs.serverGroup.clusterName"></help-field>\n </div>\n <div class="col-md-7">\n <div class="form-control-static" ng-if="!command.backingData.filtered.ecsClusters.length">\n No ECS clusters found in the selected account/region\n </div>\n <ui-select\n data-test-id="ServerGroup.clusterName"\n ng-model="command.ecsClusterName"\n ng-if="command.backingData.filtered.ecsClusters.length"\n class="form-control input-sm"\n required\n on-select="fieldChanged()"\n >\n <ui-select-match>{{$select.selected}}</ui-select-match>\n <ui-select-choices\n repeat="ecsClusterName in command.backingData.filtered.ecsClusters | filter: $select.search"\n >\n <span ng-bind-html="ecsClusterName"></span>\n </ui-select-choices>\n </ui-select>\n </div>\n </div>\n <div class="form-group">\n <div class="col-md-3 sm-label-right">\n Stack\n <help-field key="ecs.serverGroup.stack"></help-field>\n </div>\n <div class="col-md-7">\n <input\n data-test-id="ServerGroup.stack"\n type="text"\n class="form-control input-sm no-spel"\n ng-pattern="basicSettingsCtrl.stackPattern"\n name="stack"\n ng-model="command.stack"\n />\n </div>\n </div>\n <div class="form-group row slide-in" ng-if="basicSettings.stack.$error.pattern">\n <div class="col-sm-9 col-sm-offset-2 error-message">\n <span>Only dot(.) and underscore(_) special characters are allowed in the Stack field.</span>\n </div>\n </div>\n <div class="form-group">\n <div class="col-md-3 sm-label-right">\n Detail\n <help-field key="ecs.serverGroup.detail"></help-field>\n </div>\n <div class="col-md-7">\n <input\n data-test-id="ServerGroup.details"\n type="text"\n class="form-control input-sm no-spel"\n ng-pattern="basicSettingsCtrl.detailPattern"\n name="details"\n ng-model="command.freeFormDetails"\n />\n </div>\n </div>\n <div class="form-group row slide-in" ng-if="basicSettings.details.$error.pattern">\n <div class="col-sm-9 col-sm-offset-2 error-message">\n <span>Only dot(.), underscore(_), and dash(-) special characters are allowed in the Detail field.</span>\n </div>\n </div>\n <deployment-strategy-selector\n ng-if="!command.viewState.disableStrategySelection && command.selectedProvider"\n command="command"\n ></deployment-strategy-selector>\n <div class="form-group" ng-if="!command.viewState.hideClusterNamePreview">\n <div class="col-md-12">\n <div class="well-compact" ng-class="basicSettingsCtrl.showPreviewAsWarning() ? \'alert alert-warning\' : \'well\'">\n <h5 class="text-center">\n <p>Your server group will be in the cluster:</p>\n <p>\n <strong>\n {{basicSettingsCtrl.getNamePreview()}}\n <span ng-if="basicSettingsCtrl.createsNewCluster()"> (new cluster)</span>\n </strong>\n </p>\n <div\n class="text-left"\n ng-if="!basicSettingsCtrl.createsNewCluster() && command.viewState.mode === \'create\' && latestServerGroup"\n >\n <p>There is already a server group in this cluster. Do you want to clone it?</p>\n <p>\n Cloning copies the entire configuration from the selected server group, allowing you to modify whichever\n fields (e.g. image) you need to change in the new server group.\n </p>\n <p>\n To clone a server group, select "Clone" from the "Server Group Actions" menu in the details view of the\n server group.\n </p>\n <p>\n <a href ng-click="basicSettingsCtrl.navigateToLatestServerGroup()">\n Go to details for {{latestServerGroup.name}}\n </a>\n </p>\n </div>\n </h5>\n </div>\n </div>\n </div>\n </ng-form>\n</div>\n')}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/serverGroup/configure/wizard/container/container.html",'<div class="clearfix">\n <div class="col-md-12">\n <container-react\n command="command"\n notify-angular="notifyAngular"\n configure-command="configureCommand"\n ></container-react>\n </div>\n</div>\n')}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/serverGroup/configure/wizard/horizontalScaling/horizontalScaling.html",'<div class="clearfix">\n <div class="row">\n <div class="col-md-12">\n <ecs-server-group-horizontal-scaling\n command="command"\n application="application"\n capacity-provider-state="capacityProviderState"\n notify-angular="notifyAngular"\n configure-command="configureCommand"\n ></ecs-server-group-horizontal-scaling>\n </div>\n </div>\n</div>\n')}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/serverGroup/configure/wizard/networking/networking.html",'<div class="clearfix">\n <div class="col-md-12">\n <ecs-networking-react\n command="command"\n notify-angular="notifyAngular"\n configure-command="configureCommand"\n ></ecs-networking-react>\n </div>\n</div>\n')}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/serverGroup/configure/wizard/logging/logging.html",'<div class="clearfix">\n <div class="row">\n <div class="col-md-12">\n <ecs-server-group-logging command="command" application="application"></ecs-server-group-logging>\n </div>\n </div>\n</div>\n')}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/serverGroup/configure/wizard/serviceDiscovery/serviceDiscovery.html",'<div class="clearfix">\n <div class="row">\n <div class="col-md-12">\n <service-discovery-react\n command="command"\n notify-angular="notifyAngular"\n configure-command="configureCommand"\n ></service-discovery-react>\n </div>\n </div>\n</div>\n')}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/serverGroup/configure/wizard/advancedSettings/advancedSettings.html",'<div class="clearfix">\n <div class="row">\n <div class="col-md-12">\n <ecs-server-group-advanced-settings\n command="command"\n application="application"\n ></ecs-server-group-advanced-settings>\n </div>\n </div>\n</div>\n')}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/serverGroup/configure/wizard/taskDefinition/taskDefinition.html",'<div class="clearfix">\n <div class="row">\n <div class="col-md-12">\n <div class="container-fluid form-horizontal">\n <div class="form-group">\n <div class="col-md-4 sm-label-right">\n <b>Task Definition source</b>\n <help-field key="ecs.taskDefinition"></help-field>\n </div>\n <div class="col-md-2 radio">\n <label>\n <input\n data-test-id="ServerGroup.useInputs"\n type="radio"\n ng-model="command.useTaskDefinitionArtifact"\n ng-value="false"\n id="taskDefinitionSourceInputs"\n />\n Inputs\n </label>\n </div>\n <div class="col-md-1 radio">\n <label>\n <input\n data-test-id="ServerGroup.useArtifacts"\n type="radio"\n ng-model="command.useTaskDefinitionArtifact"\n ng-value="true"\n ng-disabled="command.viewState.mode === \'create\'"\n id="taskDefinitionSourceArtifact"\n />\n Artifact\n </label>\n </div>\n </div>\n <div ng-if="command.viewState.mode === \'create\'" class="color-text-caption">\n <hr />\n <span><em>Artifacts not supported outside of pipelines.</em></span>\n </div>\n </div>\n </div>\n <div class="col-md-12" ng-if="command.useTaskDefinitionArtifact">\n <hr />\n <task-definition-react\n command="command"\n notify-angular="notifyAngular"\n configure-command="configureCommand"\n ></task-definition-react>\n </div>\n </div>\n</div>\n')}]);const et="spinnaker.ecs.serverGroup.configure.wizard.advancedSettings.component";t(et,[]).component("ecsServerGroupAdvancedSettings",{bindings:{command:"=",application:"="},templateUrl:"ecs/src/serverGroup/configure/wizard/advancedSettings/advancedSettings.component.html"}),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/serverGroup/configure/wizard/advancedSettings/advancedSettings.component.html",'<div class="container-fluid form-horizontal">\n <div class="form-group">\n <div class="col-md-5 sm-label-right">\n Health Check Grace Period\n <help-field key="ecs.healthgraceperiod"></help-field>\n </div>\n <div class="col-md-2">\n <input\n type="number"\n class="form-control input-sm no-spel"\n ng-model="$ctrl.command.healthCheckGracePeriodSeconds"\n />\n </div>\n </div>\n\n <div class="form-group">\n <div class="col-md-5 sm-label-right">\n <b>ECS IAM Instance Profile</b> <help-field key="ecs.iamrole"></help-field>\n </div>\n \x3c!-- TODO - Add a help box that explains that the container does not share profiles with the host --\x3e\n\n <div class="col-md-7" ng-if="!$ctrl.command.backingData.filtered.iamRoles.length">\n No account was selected, or no IAM roles are available for ECS tasks in this account.\n </div>\n\n <div class="col-md-7" ng-if="$ctrl.command.backingData.filtered.iamRoles.length">\n <ui-select\n ng-model="$ctrl.command.iamRole"\n class="form-control input-sm"\n required\n on-select="$ctrl.fieldChanged()"\n >\n <ui-select-match>{{ $select.selected }}</ui-select-match>\n <ui-select-choices repeat="iamRole in $ctrl.command.backingData.filtered.iamRoles | filter: $select.search">\n <span ng-bind-html="iamRole"></span>\n </ui-select-choices>\n </ui-select>\n </div>\n </div>\n\n <div ng-if="!$ctrl.command.useTaskDefinitionArtifact">\n <div class="form-group">\n <div class="col-md-5 sm-label-right">\n <b>Docker Image Credentials</b> <help-field key="ecs.dockerimagecredentials"></help-field>\n </div>\n <div class="col-md-7" ng-if="!$ctrl.command.backingData.filtered.secrets.length">\n No account or region was selected, or no AWS Secrets Manager secrets are available in this account and region.\n </div>\n\n <div class="col-md-7" ng-if="$ctrl.command.backingData.filtered.secrets.length">\n <ui-select\n ng-model="$ctrl.command.dockerImageCredentialsSecret"\n class="form-control input-sm"\n required\n on-select="$ctrl.fieldChanged()"\n >\n <ui-select-match>{{ $select.selected }}</ui-select-match>\n <ui-select-choices repeat="secret in $ctrl.command.backingData.filtered.secrets | filter: $select.search">\n <span ng-bind-html="secret"></span>\n </ui-select-choices>\n </ui-select>\n </div>\n </div>\n </div>\n\n <div class="form-group">\n <div class="col-md-5 sm-label-right">\n Fargate platform version\n <help-field key="ecs.platformVersion"></help-field>\n </div>\n <div class="col-md-3">\n <input\n type="text"\n class="form-control input-sm"\n name="platformVersion"\n ng-model="$ctrl.command.platformVersion"\n />\n </div>\n </div>\n\n <div class="form-group">\n <div class="col-md-5 sm-label-right">\n Enable Deployment Circuit Breaker\n <help-field key="ecs.enableDeploymentCircuitBreaker"></help-field>\n </div>\n <div class="col-md-3">\n <input type="checkbox" ng-model="$ctrl.command.enableDeploymentCircuitBreaker" />\n </div>\n </div>\n\n <div class="form-group">\n <div class="col-md-5 sm-label-right">\n <b>Placement Strategy</b> <help-field key="ecs.placementStrategy"></help-field>\n </div>\n <div class="col-md-7">\n <ui-select ng-model="$ctrl.command.placementStrategyName" class="form-control input-sm">\n <ui-select-match>{{ $select.selected }}</ui-select-match>\n <ui-select-choices\n repeat="item in [\'AZ Balanced Spread\', \'AZ Balanced BinPack CPU\', \'AZ Balanced BinPack Memory\', \'BinPack CPU\', \'BinPack Memory\', \'One Task Per Host\', \'None\'] | filter: $select.search"\n >\n <span ng-bind-html="item"></span>\n </ui-select-choices>\n </ui-select>\n \x3c!-- TODO - implement handling of custom placement strategies and constraints --\x3e\n </div>\n </div>\n\n <div class="form-group">\n <div class="sm-label-left">\n <b>Placement Constraints</b>\n <help-field key="ecs.placementConstraints"></help-field>\n </div>\n <form name="ecsPlacementConstraints">\n <table class="table table-condensed packed tags">\n <thead>\n <tr>\n <th style="width: 25%">Type <help-field key="ecs.placementConstraintType"></help-field></th>\n <th style="width: 68%">Expression <help-field key="ecs.placementConstraintExpression"></help-field></th>\n <th></th>\n </tr>\n </thead>\n <tbody>\n <tr ng-repeat="constraint in $ctrl.command.placementConstraints">\n <td>\n <select\n class="form-control input-sm"\n ng-model="constraint.type"\n ng-options="type for type in [\'distinctInstance\', \'memberOf\']"\n ></select>\n </td>\n <td>\n <input type="text" class="form-control input-sm no-spel" ng-model="constraint.expression" />\n </td>\n <td>\n <div class="form-control-static">\n <a class="btn-link sm-label" ng-click="$ctrl.command.placementConstraints.splice($index, 1)">\n <span class="glyphicon glyphicon-trash"></span>\n <span class="sr-only">Remove</span>\n </a>\n </div>\n </td>\n </tr>\n </tbody>\n <tfoot>\n <tr>\n <td colspan="3">\n <button class="btn btn-block btn-sm add-new" ng-click="$ctrl.command.placementConstraints.push({})">\n <span class="glyphicon glyphicon-plus-sign"></span>\n Add New Placement Constraint\n </button>\n </td>\n </tr>\n </tfoot>\n </table>\n </form>\n </div>\n\n <div ng-if="!$ctrl.command.useTaskDefinitionArtifact">\n <div class="form-group">\n <div class="sm-label-left">\n <b>Docker labels (optional)</b>\n <help-field key="ecs.dockerLabels"></help-field>\n </div>\n <map-editor model="$ctrl.command.dockerLabels" allow-empty="true"></map-editor>\n </div>\n\n <div class="form-group">\n <div class="sm-label-left">\n <b>Environment Variables (optional)</b>\n <help-field key="ecs.environmentVariables"></help-field>\n </div>\n <map-editor model="$ctrl.command.environmentVariables" allow-empty="true"></map-editor>\n </div>\n </div>\n\n <div class="form-group">\n <div class="sm-label-left">\n <b>Tags (optional)</b>\n <help-field key="ecs.tags"></help-field>\n </div>\n <map-editor model="$ctrl.command.tags" allow-empty="true"></map-editor>\n </div>\n\n <div ng-if="$ctrl.command.useTaskDefinitionArtifact" style="color: #666">\n <hr />\n <p>\n <em\n ><strong>Docker Image Credentials, Docker labels</strong>, and <strong>Environment Variables</strong> cannot be\n individually set when using a Task Definition artifact. Please include them in their respective container\n definition in that file.\n </em>\n </p>\n </div>\n</div>\n')}]);class tt extends ue.Component{constructor(e){super(e),this.getAvailableCapacityProviders=e=>e.backingData&&e.backingData.filtered&&e.backingData.filtered.availableCapacityProviders?e.backingData.filtered.availableCapacityProviders:[],this.getDefaultCapacityProviderStrategy=e=>e.backingData&&e.backingData.filtered&&e.backingData.filtered.defaultCapacityProviderStrategy?e.backingData.filtered.defaultCapacityProviderStrategy:[],this.getCapacityProviderStrategy=(e,t)=>e&&t.backingData&&t.backingData.filtered&&t.backingData.filtered.defaultCapacityProviderStrategy?t.backingData.filtered.defaultCapacityProviderStrategy:this.state.capacityProviderStrategy,this.addCapacityProviderStrategy=()=>{const e=this.state.capacityProviderStrategy;e.push({capacityProvider:"",base:null,weight:null}),this.props.notifyAngular("capacityProviderStrategy",e),this.setState({capacityProviderStrategy:e})},this.removeCapacityProviderStrategy=e=>{const t=this.state.capacityProviderStrategy;t.splice(e,1),this.props.notifyAngular("capacityProviderStrategy",t),this.setState({capacityProviderStrategy:t})},this.updateCapacityProviderName=(e,t)=>{const n=this.state.capacityProviderStrategy;n[e].capacityProvider=t,this.props.notifyAngular("capacityProviderStrategy",n),this.setState({capacityProviderStrategy:n}),this.props.command.viewState.dirty.customCapacityProviders=[]},this.updateCapacityProviderBase=(e,t)=>{const n=this.state.capacityProviderStrategy;n[e].base=t,this.props.notifyAngular("capacityProviderStrategy",n),this.setState({capacityProviderStrategy:n})},this.updateCapacityProviderWeight=(e,t)=>{const n=this.state.capacityProviderStrategy;n[e].weight=t,this.props.notifyAngular("capacityProviderStrategy",n),this.setState({capacityProviderStrategy:n})},this.updateCapacityProviderType=e=>{this.setState({useDefaultCapacityProviders:e}),this.props.notifyAngular("useDefaultCapacityProviders",e),this.props.command.viewState.dirty.customCapacityProviders=[];const t=e&&this.state.defaultCapacityProviderStrategy.length>0?this.state.defaultCapacityProviderStrategy:[];this.setState({capacityProviderStrategy:t}),this.props.notifyAngular("capacityProviderStrategy",t)};const t=this.props.command;this.state={availableCapacityProviders:this.getAvailableCapacityProviders(t),defaultCapacityProviderStrategy:this.getDefaultCapacityProviderStrategy(t),ecsClusterName:t.ecsClusterName,useDefaultCapacityProviders:t.useDefaultCapacityProviders||t.capacityProviderStrategy&&0==t.capacityProviderStrategy.length,capacityProviderStrategy:t.capacityProviderStrategy&&t.capacityProviderStrategy.length>0?t.capacityProviderStrategy:[],capacityProviderLoadedFlag:!1}}componentDidMount(){this.props.configureCommand("1").then((()=>{const e=this.props.command,t=this.state.useDefaultCapacityProviders;this.setState({availableCapacityProviders:this.getAvailableCapacityProviders(e),defaultCapacityProviderStrategy:this.getDefaultCapacityProviderStrategy(e),capacityProviderStrategy:this.getCapacityProviderStrategy(t,e),capacityProviderLoadedFlag:!0}),this.props.notifyAngular("useDefaultCapacityProviders",this.state.useDefaultCapacityProviders),this.props.notifyAngular("capacityProviderStrategy",this.state.capacityProviderStrategy)}))}render(){const e=this.updateCapacityProviderName,t=this.updateCapacityProviderBase,n=this.updateCapacityProviderWeight,a=this.addCapacityProviderStrategy,r=this.removeCapacityProviderStrategy,i=this.updateCapacityProviderType,s=this.state.capacityProviderStrategy,o=this.state.useDefaultCapacityProviders,l=this.state.capacityProviderLoadedFlag,c=this.props.command.viewState.dirty&&this.props.command.viewState.dirty.customCapacityProviders?this.props.command.viewState.dirty.customCapacityProviders:[],d=this.props.command.viewState.dirty&&this.props.command.viewState.dirty.defaulCapacityProviders?this.props.command.viewState.dirty.defaulCapacityProviders:[],p=this.state.availableCapacityProviders&&this.state.availableCapacityProviders.length>0?this.state.availableCapacityProviders.map((e=>({label:`${e}`,value:e}))):[],u=o&&d?ue.createElement("div",{className:"alert alert-warning"},ue.createElement("p",{className:"text-left"},ue.createElement("i",{className:"fa fa-exclamation-triangle"}),"Invalid capacity providers are a part of default capacity provider strategy.",ue.createElement("br",null),"Please click 'Done' to use current default capacity provider strategy (shown below) or switch to using a custom strategy.")):"",m=c?c.map((function(e,t){return ue.createElement("li",{key:t},e)})):"",g=o&&d.length>0?u:c.length>0&&!o?ue.createElement("div",{className:"alert alert-warning"},ue.createElement("p",null,ue.createElement("i",{className:"fa fa-exclamation-triangle"}),"The following capacity providers could not be found in the selected account/region/cluster and were removed:"),ue.createElement("ul",null,m),ue.createElement("br",null),ue.createElement("p",{className:"text-left"},"Please select the capacity provider(s) from the dropdown to resolve this error.")):"",v=s.length>0?s.map((function(a,i){return ue.createElement("tr",{key:i},o?ue.createElement("td",null,ue.createElement("input",{"data-test-id":"ServerGroup.defaultCapacityProvider.name."+i,type:"string",className:"form-control input-sm no-spel",required:!0,value:a.capacityProvider,disabled:!0})):ue.createElement("td",{"data-test-id":"ServerGroup.customCapacityProvider.name."+i},ue.createElement(M,{placeholder:"Select capacity provider",options:p,value:a.capacityProvider,onChange:t=>{e(i,t.label)},clearable:!1})),ue.createElement("td",null,ue.createElement("input",{"data-test-id":"ServerGroup.capacityProvider.base."+i,disabled:o,type:"number",className:"form-control input-sm no-spel",value:a.base,onChange:e=>t(i,e.target.valueAsNumber)})),ue.createElement("td",null,ue.createElement("input",{"data-test-id":"ServerGroup.capacityProvider.weight."+i,disabled:o,type:"number",className:"form-control input-sm no-spel",required:!0,value:a.weight,onChange:e=>n(i,e.target.valueAsNumber)})),o?"":ue.createElement("td",null,ue.createElement("div",{className:"form-control-static"},ue.createElement("a",{className:"btn-link sm-label",onClick:()=>r(i)},ue.createElement("span",{className:"glyphicon glyphicon-trash"}),ue.createElement("span",{className:"sr-only"},"Remove")))))})):o&&0==this.state.capacityProviderStrategy.length?ue.createElement("tr",null,ue.createElement("div",{className:"sm-label-left",style:{width:"200%"}},ue.createElement(he,{color:"warning"}," ","The cluster does not have a default capacity provider strategy defined. Set a default capacity provider strategy or use a custom strategy."))):"",h=this.state.ecsClusterName&&this.props.command.credentials&&this.props.command.region&&!o&&p.length>0?ue.createElement("button",{"data-test-id":"ServerGroup.addCapacityProvider",className:"btn btn-block btn-sm add-new",onClick:a},ue.createElement("span",{className:"glyphicon glyphicon-plus-sign"}),"Add New Capacity Provider"):!o&&l&&0==p.length?ue.createElement("div",{className:"sm-label-left",style:{width:"200%"}},ue.createElement(he,{color:"warning"}," The cluster does not have capacity providers defined. ")):"";return ue.createElement("div",null,(c.length>0||d.length>0)&&l?ue.createElement("div",null,g):"",ue.createElement("div",{className:"sm-label-left"},ue.createElement("b",null,"Capacity Provider Strategy"),ue.createElement(R,{id:"ecs.capacityProviderStrategy"})," ",ue.createElement("br",null),ue.createElement("span",null,"(",this.state.ecsClusterName,")")),ue.createElement("div",{className:"radio"},ue.createElement("label",null,ue.createElement("input",{"data-test-id":"ServerGroup.capacityProviders.default",type:"radio",checked:o,onClick:()=>i(!0),id:"computeOptionsLaunchType1"}),"Use cluster default")),ue.createElement("div",{className:"radio"},ue.createElement("label",null,ue.createElement("input",{"data-test-id":"ServerGroup.capacityProviders.custom",type:"radio",checked:!o,onClick:()=>i(!1),id:"computeOptionsCapacityProviders2"}),"Use custom (Advanced)")),l?ue.createElement("table",{className:"table table-condensed packed tags"},ue.createElement("thead",null,ue.createElement("tr",null,ue.createElement("th",{style:{width:"50%"}},"Provider name",ue.createElement(R,{id:"ecs.capacityProviderName"})),ue.createElement("th",{style:{width:"25%"}},"Base",ue.createElement(R,{id:"ecs.capacityProviderBase"})),ue.createElement("th",{style:{width:"25%"}},"Weight",ue.createElement(R,{id:"ecs.capacityProviderWeight"})))),ue.createElement("tbody",null,v),ue.createElement("tfoot",null,ue.createElement("tr",null,ue.createElement("td",{colSpan:4},h)))):ue.createElement("div",{className:"load medium"},ue.createElement("div",{className:"message"},"Loading capacity providers..."),ue.createElement("div",{className:"bars"},ue.createElement("div",{className:"bar"}),ue.createElement("div",{className:"bar"}),ue.createElement("div",{className:"bar"}))))}}const nt="spinnaker.ecs.serverGroup.configure.wizard.capacityProvider.react";t(nt,[]).component("ecsCapacityProviderReact",fe($(tt,"ecsCapacityProviderReact"),["command","notifyAngular","configureCommand"]));class at extends pe.Component{constructor(e){super(e),this.getIdToImageMap=()=>{const e=new Map;return this.props.command.backingData.filtered.images.forEach((t=>{e.set(t.imageId,t)})),e},this.getEmptyImageDescription=()=>({imageId:"",message:"",fromTrigger:!1,fromContext:!1,stageId:"",imageLabelOrSha:"",account:"",registry:"",repository:"",tag:""}),this.pushTargetGroupMapping=()=>{const e=this.state.targetGroupMappings;e.push({containerName:"",targetGroup:"",containerPort:80}),this.setState({targetGroupMappings:e})},this.updateContainerMappingImage=e=>{let t=this.getIdToImageMap().get(e.value);t||(t=this.getEmptyImageDescription()),this.props.notifyAngular("imageDescription",t),this.setState({imageDescription:t})},this.updateComputeUnits=e=>{this.props.notifyAngular("computeUnits",e),this.setState({computeUnits:e})},this.updateReservedMemory=e=>{this.props.notifyAngular("reservedMemory",e),this.setState({reservedMemory:e})},this.updateTargetGroupMappingTargetGroup=(e,t)=>{const n=this.state.targetGroupMappings;n[e].targetGroup=t.value,this.props.notifyAngular("targetGroupMappings",n),this.setState({targetGroupMappings:n}),this.updateDirtyTargetGroups()},this.updateTargetGroupMappingPort=(e,t)=>{const n=this.state.targetGroupMappings;n[e].containerPort=t,this.props.notifyAngular("targetGroupMappings",n),this.setState({targetGroupMappings:n})},this.removeTargetGroupMapping=e=>{const t=this.state.targetGroupMappings;t.splice(e,1),this.props.notifyAngular("targetGroupMappings",t),this.setState({targetGroupMappings:t})},this.updateDirtyTargetGroups=()=>{this.props.command.viewState.dirty.targetGroups=[]};const t=this.props.command;let n="";t.containerMappings&&t.containerMappings.length>0&&(n=t.containerMappings[0].containerName);let a=[];t.targetGroupMappings&&t.targetGroupMappings.length>0&&(a=t.targetGroupMappings),t.targetGroup&&t.targetGroup.length>0&&(a.push({containerName:t.loadBalancedContainer||n,targetGroup:t.targetGroup,containerPort:t.containerPort}),t.targetGroup="",t.loadBalancedContainer=""),t.targetGroupMappings=re(a,W),t.containerMappings=null,this.state={imageDescription:t.imageDescription?t.imageDescription:this.getEmptyImageDescription(),computeUnits:t.computeUnits,reservedMemory:t.reservedMemory,dockerImages:t.backingData&&t.backingData.filtered?t.backingData.filtered.images:[],targetGroupMappings:t.targetGroupMappings,targetGroupsAvailable:t.backingData&&t.backingData.filtered?t.backingData.filtered.targetGroups:[]},this.state.targetGroupMappings.forEach((e=>{e.containerName=""}))}componentDidMount(){this.props.configureCommand("1").then((()=>{this.setState({dockerImages:this.props.command.backingData.filtered.images,targetGroupsAvailable:this.props.command.backingData.filtered.targetGroups})}))}render(){const e=this.removeTargetGroupMapping,t=this.updateContainerMappingImage,n=this.updateTargetGroupMappingTargetGroup,a=this.updateTargetGroupMappingPort,r=this.updateComputeUnits,i=this.updateReservedMemory,s=this.props.command.viewState.dirty&&this.props.command.viewState.dirty.targetGroups?this.props.command.viewState.dirty.targetGroups:[],o=this.state.dockerImages.map((function(e){let t="";return(e.fromTrigger||e.fromContext)&&(t=e.fromTrigger?"(TRIGGER) ":"(FIND IMAGE RESULT) "),{label:`${t} (${e.imageId})`,value:e.imageId}})),l=s?s.map((function(e,t){return pe.createElement("li",{key:t},e)})):"",c=pe.createElement("div",{className:"alert alert-warning"},pe.createElement("p",null,pe.createElement("i",{className:"fa fa-exclamation-triangle"}),"The following target groups could not be found in the selected account/region/VPC and were removed:"),pe.createElement("ul",null,l),pe.createElement("br",null),pe.createElement("p",{className:"text-left"},"Please select the target group(s) from the dropdown to resolve this error.")),d=this.state.targetGroupsAvailable.length?pe.createElement("button",{className:"btn btn-block btn-sm add-new","data-test-id":"ContainerInputs.targetGroupAdd",onClick:this.pushTargetGroupMapping},pe.createElement("span",{className:"glyphicon glyphicon-plus-sign"}),"Add New Target Group Mapping"):pe.createElement("div",{className:"sm-label-left"},pe.createElement(he,{color:"warning"},"No target groups found in the selected account/region/VPC")),p=this.state.targetGroupsAvailable.map((function(e){return{label:`${e}`,value:e}})),u=this.state.targetGroupMappings.map((function(t,r){return pe.createElement("tr",{key:r},pe.createElement("td",{"data-test-id":"ContainerInputs.targetGroup"},pe.createElement(M,{placeholder:"Select a target group to use...",options:p,value:t.targetGroup.toString(),onChange:e=>n(r,e),clearable:!1})),pe.createElement("td",null,pe.createElement("input",{"data-test-id":"ContainerInputs.targetGroupPort",type:"number",className:"form-control input-sm no-spel",required:!0,value:t.containerPort.toString(),onChange:e=>a(r,e.target.valueAsNumber)})),pe.createElement("td",null,pe.createElement("div",{className:"form-control-static"},pe.createElement("a",{className:"btn-link sm-label","data-test-id":"ContainerInputs.targetGroupRemove",onClick:()=>e(r)},pe.createElement("span",{className:"glyphicon glyphicon-trash"}),pe.createElement("span",{className:"sr-only"},"Remove")))))}));return pe.createElement("div",{className:"container-fluid form-horizontal"},s.length>0?pe.createElement("div",null,c):"",pe.createElement("div",{className:"form-group"},pe.createElement("div",{className:"col-md-3 sm-label-right"},pe.createElement("b",null,"Container Image"),pe.createElement(R,{id:"ecs.containerMappingImage"})),pe.createElement("div",{className:"col-md-9","data-test-id":"ContainerInputs.containerImage"},pe.createElement(M,{placeholder:"Select an image to use...",options:o,value:this.state.imageDescription.imageId,onChange:e=>{t(e)},clearable:!1}))),pe.createElement("div",{className:"form-group"},pe.createElement("div",{className:"col-md-3 sm-label-right"},pe.createElement("b",null,"Compute Units"),pe.createElement(R,{id:"ecs.capacity.reserved.computeUnits"})),pe.createElement("div",{className:"col-md-9",style:{width:"100px"}},pe.createElement("input",{"data-test-id":"ContainerInputs.computeUnits",type:"number",className:"form-control input-sm no-spel",required:!1,value:this.state.computeUnits,onChange:e=>r(e.target.valueAsNumber)}))),pe.createElement("div",{className:"form-group"},pe.createElement("div",{className:"col-md-3 sm-label-right"},pe.createElement("b",null,"Reserved Memory"),pe.createElement(R,{id:"ecs.capacity.reserved.memory"})),pe.createElement("div",{className:"col-md-9",style:{width:"100px"}},pe.createElement("input",{"data-test-id":"ContainerInputs.reservedMemory",type:"number",className:"form-control input-sm no-spel",required:!1,value:this.state.reservedMemory,onChange:e=>i(e.target.valueAsNumber)}))),pe.createElement("div",{className:"form-group"},pe.createElement("div",{className:"sm-label-left"},pe.createElement("b",null,"Target Group Mappings"),pe.createElement(R,{id:"ecs.targetGroupMappings"})),pe.createElement("form",{name:"ecsContainerTargetGroupMappings"},pe.createElement("table",{className:"table table-condensed packed tags"},pe.createElement("thead",null,pe.createElement("tr",{key:"header"},pe.createElement("th",{style:{width:"80%"}},"Target group",pe.createElement(R,{id:"ecs.loadBalancer.targetGroup"})),pe.createElement("th",{style:{width:"20%"}},"Target port",pe.createElement(R,{id:"ecs.loadbalancing.targetPort"})),pe.createElement("th",null))),pe.createElement("tbody",null,u),pe.createElement("tfoot",null,pe.createElement("tr",null,pe.createElement("td",{colSpan:4},d)))))))}}const rt="spinnaker.ecs.serverGroup.configure.wizard.container.react";t(rt,[]).component("containerReact",fe($(at,"containerReact"),["command","notifyAngular","configureCommand"]));const it="spinnaker.ecs.serverGroup.configure.wizard.horizontalScaling.component";t(it,[]).component("ecsServerGroupHorizontalScaling",{bindings:{command:"=",application:"=",capacityProviderState:"=",notifyAngular:"=",configureCommand:"="},templateUrl:"ecs/src/serverGroup/configure/wizard/horizontalScaling/horizontalScaling.component.html"}),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/serverGroup/configure/wizard/horizontalScaling/horizontalScaling.component.html",'<div class="container-fluid form-horizontal">\n <div class="form-group">\n <div class="col-md-4 sm-label-right">\n <b>Compute options</b>\n <help-field key="ecs.computeOptions"></help-field>\n </div>\n <div class="col-md-2 radio">\n <label>\n <input\n data-test-id="ServerGroup.computeOptionsLaunchType"\n type="radio"\n ng-model="$ctrl.capacityProviderState.useCapacityProviders"\n ng-value="false"\n ng-click="$ctrl.capacityProviderState.updateComputeOption(\'launchType\')"\n id="computeOptionsLaunchType"\n />\n Launch type\n </label>\n </div>\n <div class="col-md-1 radio">\n <label>\n <input\n data-test-id="ServerGroup.computeOptionsCapacityProviders"\n type="radio"\n ng-model="$ctrl.capacityProviderState.useCapacityProviders"\n ng-value="true"\n ng-click="$ctrl.capacityProviderState.updateComputeOption(\'capacityProviders\')"\n id="computeOptionsCapacityProviders"\n />\n Capacity Providers\n </label>\n </div>\n </div>\n\n <div class="form-group" ng-if="$ctrl.capacityProviderState.useCapacityProviders">\n <ecs-capacity-provider-react\n command="$ctrl.command"\n notify-angular="$ctrl.notifyAngular"\n configure-command="$ctrl.configureCommand"\n ></ecs-capacity-provider-react>\n </div>\n\n <div class="form-group" ng-if="!$ctrl.capacityProviderState.useCapacityProviders" style="padding-top: 10px">\n <div class="col-md-5 sm-label-right">\n Launch Type\n <help-field key="ecs.launchtype"></help-field>\n </div>\n <div class="col-md-3" data-test-id="ServerGroup.launchType">\n <ui-select ng-model="$ctrl.command.launchType" class="form-control input-sm">\n <ui-select-match placeholder="Select...">{{ $select.selected }}</ui-select-match>\n <ui-select-choices repeat="launchType in $ctrl.command.backingData.launchTypes | filter: $select.search">\n <span ng-bind-html="launchType | highlight: $select.search"></span>\n </ui-select-choices>\n </ui-select>\n </div>\n </div>\n\n <hr />\n\n <div class="form-group">\n <div class="col-md-5 sm-label-right">\n Desired capacity\n <help-field key="ecs.capacity.desired"></help-field>\n </div>\n <div class="col-md-2">\n <input\n type="number"\n class="form-control input-sm no-spel"\n name="capacity"\n ng-model="$ctrl.command.capacity.desired"\n />\n </div>\n </div>\n\n <div class="form-group">\n <div class="col-md-5 sm-label-right">\n Minimum\n <help-field key="ecs.capacity.minimum"></help-field>\n </div>\n <div class="col-md-2">\n <input type="number" class="form-control input-sm no-spel" name="min" ng-model="$ctrl.command.capacity.min" />\n </div>\n </div>\n\n <div class="form-group">\n <div class="col-md-5 sm-label-right">\n Maximum\n <help-field key="ecs.capacity.maximum"></help-field>\n </div>\n <div class="col-md-2">\n <input type="number" class="form-control input-sm no-spel" name="max" ng-model="$ctrl.command.capacity.max" />\n </div>\n </div>\n\n <div class="form-group">\n <div class="col-md-12 checkbox">\n <label>\n <input\n type="checkbox"\n ng-model="$ctrl.command.useSourceCapacity"\n ng-change="$ctrl.command.preferSourceCapacity=$ctrl.command.useSourceCapacity"\n />\n <b>If available, use the previous server group\'s capacity</b>\n </label>\n <help-field key="ecs.capacity.overwrite"></help-field>\n </div>\n </div>\n\n <div class="form-group">\n <div class="col-md-12 checkbox">\n <label>\n <input type="checkbox" ng-model="$ctrl.command.copySourceScalingPoliciesAndActions" />\n <b>If available, copy the previous server group\'s autoscaling policies</b>\n </label>\n <help-field key="ecs.capacity.copySourceScalingPoliciesAndActions"></help-field>\n </div>\n </div>\n</div>\n')}]);const st="spinnaker.ecs.serverGroup.configure.basicSettings";e.module(st,[V,_]).controller("ecsServerGroupBasicSettingsCtrl",["$scope","$controller","$uibModalStack","$state",function(t,n,a,r){e.extend(this,n("BasicSettingsMixin",{$scope:t,$uibModalStack:a,$state:r})),t.$watch("form.$valid",(function(e){e?(x.markClean("basicSettings"),x.markComplete("basicSettings")):x.markIncomplete("basicSettings")}))}]);const ot="spinnaker.ecs.serverGroup.configure.wizard.logging.component";t(ot,[]).component("ecsServerGroupLogging",{bindings:{command:"=",application:"="},templateUrl:"ecs/src/serverGroup/configure/wizard/logging/logging.component.html"}),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/serverGroup/configure/wizard/logging/logging.component.html",'<div class="container-fluid form-horizontal">\n <div class="form-group">\n <div class="col-md-5 sm-label-right">\n <b>Log driver (Optional)</b> <help-field key="ecs.logDriver"></help-field>\n </div>\n <div class="col-md-7">\n <ui-select ng-model="$ctrl.command.logDriver" class="form-control input-sm" data-test-id="Logging.logDriver">\n <ui-select-match>{{ $select.selected }}</ui-select-match>\n <ui-select-choices\n repeat="item in [\'None\', \'awslogs\', \'fluentd\', \'gelf\', \'journald\', \'json-file\', \'logentries\', \'splunk\', \'sumologic\', \'syslog\'] | filter: $select.search"\n >\n <span ng-bind-html="item"></span>\n </ui-select-choices>\n </ui-select>\n </div>\n </div>\n\n <div class="form-group" ng-if="$ctrl.command.logDriver && $ctrl.command.logDriver !== \'None\'">\n <div class="sm-label-left">\n <b>Logging options (optional)</b>\n <help-field key="ecs.logOptions"></help-field>\n </div>\n <map-editor model="$ctrl.command.logOptions" allow-empty="true"></map-editor>\n </div>\n\n <div class="form-group" ng-if="!$ctrl.command.logDriver || $ctrl.command.logDriver == \'None\'">\n Logging options are not available for your log driver selection.\n </div>\n</div>\n')}]);class lt extends pe.Component{constructor(e){super(e),this.updateNetworkMode=e=>{const t=e.value,n=this.props.command;this.props.notifyAngular("networkMode",t),this.setState({networkMode:t,subnetTypesAvailable:n.backingData&&n.backingData.filtered&&n.backingData.filtered.subnetTypes?n.backingData.filtered.subnetTypes:[]})},this.updateSecurityGroups=e=>{const t=Array.isArray(e)?e.map((e=>e.value)):[];this.props.notifyAngular("securityGroupNames",t),this.setState({securityGroupNames:t})},this.updateSubnetTypes=e=>{const t=this.props.command,n=Array.isArray(e)?e.map((e=>e.value)):[];this.props.notifyAngular("subnetTypes",n),t.subnetTypeChanged(t),this.setState({subnetTypes:n,securityGroupsAvailable:t.backingData&&t.backingData.filtered&&t.backingData.filtered.securityGroupNames?t.backingData.filtered.securityGroupNames:[]})},this.updateAssociatePublicIpAddress=e=>{this.props.notifyAngular("associatePublicIpAddress",e),this.setState({associatePublicIpAddress:e})};const t=this.props.command;let n=[];t.subnetTypes&&t.subnetTypes.length>0&&(n=t.subnetTypes),t.subnetType&&t.subnetType.length>0&&(n.push(t.subnetType),t.subnetType=""),t.subnetTypes=re(n,W),this.state={associatePublicIpAddress:t.associatePublicIpAddress,networkMode:t.networkMode,networkModesAvailable:t.backingData&&t.backingData.networkModes?t.backingData.networkModes:[],securityGroupNames:t.securityGroupNames,securityGroupsAvailable:t.backingData&&t.backingData.filtered&&t.backingData.filtered.securityGroupNames?t.backingData.filtered.securityGroupNames:[],subnetTypes:t.subnetTypes,subnetTypesAvailable:t.backingData&&t.backingData.filtered&&t.backingData.filtered.subnetTypes?t.backingData.filtered.subnetTypes:[]}}componentDidMount(){const e=this.props.command;this.props.configureCommand("1").then((()=>{this.setState({networkModesAvailable:e.backingData&&e.backingData.networkModes?e.backingData.networkModes:[],securityGroupsAvailable:e.backingData&&e.backingData.filtered&&e.backingData.filtered.securityGroupNames?e.backingData.filtered.securityGroupNames:[],subnetTypesAvailable:e.backingData&&e.backingData.filtered&&e.backingData.filtered.subnetTypes?e.backingData.filtered.subnetTypes:[]})}))}render(){const e=this.updateAssociatePublicIpAddress,t=this.updateNetworkMode,n=this.updateSecurityGroups,a=this.updateSubnetTypes,r=this.state.networkModesAvailable.map((function(e){return{label:`${e}`,value:e}})),i=this.state.securityGroupsAvailable.map((function(e){return{label:`${e}`,value:e}})),s=this.state.subnetTypesAvailable.map((function(e){return{label:`${e.purpose} (${e.vpcId})`,value:e.purpose}})),o=this.state.subnetTypesAvailable.length?pe.createElement(M,{multi:!0,options:s,value:this.state.subnetTypes,onChange:e=>{a(e)}}):pe.createElement(he,{color:"warning"},"No account was selected, or no subnet types are available for this account"),l=this.state.securityGroupsAvailable.length?pe.createElement(M,{multi:!0,options:i,value:this.state.securityGroupNames,onChange:e=>{n(e)}}):pe.createElement(he,{color:"warning"},"No security groups found in the selected account/region"),c="awsvpc"===this.state.networkMode?pe.createElement("div",{className:"form-group"},pe.createElement("div",{className:"form-group"},pe.createElement("div",{className:"col-md-3 sm-label-right"},pe.createElement("b",null,"VPC Subnet"),pe.createElement(R,{key:"ecs.subnet"})),pe.createElement("div",{className:"col-md-9","data-test-id":"Networking.subnetType"},o)),pe.createElement("div",{className:"form-group"},pe.createElement("div",{className:"col-md-3 sm-label-right"},pe.createElement("b",null,"Security Groups"),pe.createElement(R,{key:"ecs.securityGroups"})),pe.createElement("div",{className:"col-md-9","data-test-id":"Networking.securityGroups"},l)),pe.createElement("div",{className:"form-group"},pe.createElement("div",{className:"col-md-3 sm-label-right"},pe.createElement("b",null,"Associate Public IP Address"),pe.createElement(R,{key:"ecs.publicip"})),pe.createElement("div",{className:"col-md-1 radio"},pe.createElement("label",null,pe.createElement("input",{"data-test-id":"Networking.associatePublicIpAddressTrue",type:"radio",value:"true",id:"associatePublicIpAddressTrue",checked:!0===this.state.associatePublicIpAddress,onChange:()=>e(!0)}),"Yes")),pe.createElement("div",{className:"col-md-1 radio"},pe.createElement("label",null,pe.createElement("input",{"data-test-id":"Networking.associatePublicIpAddressFalse",type:"radio",value:"false",id:"associatePublicIpAddressFalse",checked:!1===this.state.associatePublicIpAddress,onChange:()=>e(!1)}),"No")))):pe.createElement("div",{className:"col-md-3 sm-label-right"});return pe.createElement("div",{className:"networking-fluid form-horizontal"},pe.createElement("div",{className:"form-group"},pe.createElement("div",{className:"form-group"},pe.createElement("div",{className:"col-md-3 sm-label-right"},pe.createElement("b",null,"Network Mode"),pe.createElement(R,{id:"ecs.networkMode"})),pe.createElement("div",{className:"col-md-9","data-test-id":"Networking.networkMode"},pe.createElement(M,{placeholder:"Select a network mode to use ...",options:r,value:this.state.networkMode,onChange:e=>{t(e)}})))),c)}}const ct="spinnaker.ecs.serverGroup.configure.wizard.networking.react";t(ct,[]).component("ecsNetworkingReact",fe($(lt,"ecsNetworkingReact"),["command","notifyAngular","configureCommand"]));class dt extends ue.Component{constructor(e){super(e),this.getNameToRegistryMap=()=>{const e=new Map;return this.props.command.backingData.filtered.serviceDiscoveryRegistries.forEach((t=>{e.set(t.displayName,t)})),e},this.getEmptyRegistry=()=>({account:"",region:"",name:"",id:"",arn:"",displayName:""}),this.updateServiceDiscoveryRegistry=(e,t)=>{let n=this.getNameToRegistryMap().get(t.value);n||(n=this.getEmptyRegistry());const a=this.state.serviceDiscoveryAssociations;a[e].registry=n,this.props.notifyAngular("serviceDiscoveryAssociations",a),this.setState({serviceDiscoveryAssociations:a})},this.updateServiceDiscoveryPort=(e,t)=>{const n=this.state.serviceDiscoveryAssociations;n[e].containerPort=t,this.props.notifyAngular("serviceDiscoveryAssociations",n),this.setState({serviceDiscoveryAssociations:n})},this.updateServiceDiscoveryContainerName=(e,t)=>{const n=this.state.serviceDiscoveryAssociations;n[e].containerName=t,this.props.notifyAngular("serviceDiscoveryAssociations",n),this.setState({serviceDiscoveryAssociations:n})},this.pushServiceDiscoveryAssociation=()=>{const e=this.state.serviceDiscoveryAssociations;e.push({registry:this.getEmptyRegistry(),containerPort:80,containerName:""}),this.setState({serviceDiscoveryAssociations:e})},this.removeServiceDiscoveryAssociations=e=>{const t=this.state.serviceDiscoveryAssociations;t.splice(e,1),this.props.notifyAngular("serviceDiscoveryAssociations",t),this.setState({serviceDiscoveryAssociations:t})};const t=this.props.command;this.state={serviceDiscoveryAssociations:t.serviceDiscoveryAssociations,serviceDiscoveryRegistriesAvailable:t.backingData&&t.backingData.filtered?t.backingData.filtered.serviceDiscoveryRegistries:[],useTaskDefinitionArtifact:t.useTaskDefinitionArtifact},this.state.useTaskDefinitionArtifact||this.state.serviceDiscoveryAssociations.forEach((e=>{e.containerName=null}))}componentDidMount(){this.props.configureCommand("1").then((()=>{this.setState({serviceDiscoveryRegistriesAvailable:this.props.command.backingData.filtered.serviceDiscoveryRegistries})}))}render(){const e=this.removeServiceDiscoveryAssociations,t=this.updateServiceDiscoveryRegistry,n=this.updateServiceDiscoveryPort,a=this.updateServiceDiscoveryContainerName,r=this.state.serviceDiscoveryRegistriesAvailable.map((function(e){return{label:`${e.displayName}`,value:e.displayName}})),i=this.state.useTaskDefinitionArtifact,s=this.state.serviceDiscoveryAssociations.map((function(s,o){return ue.createElement("tr",{key:o},i&&ue.createElement("td",null,ue.createElement("input",{className:"form-control input-sm",placeholder:"Enter a container name ...",required:!0,value:s.containerName,onChange:e=>a(o,e.target.value)})),ue.createElement("td",null,ue.createElement(M,{placeholder:"Select a registry...",options:r,value:s.registry.displayName.toString(),onChange:e=>t(o,e),clearable:!1,required:!0})),ue.createElement("td",null,ue.createElement("input",{type:"number",className:"form-control input-sm no-spel",required:!0,value:s.containerPort,onChange:e=>n(o,e.target.valueAsNumber)})),ue.createElement("td",null,ue.createElement("div",{className:"form-control-static"},ue.createElement("a",{className:"btn-link sm-label",onClick:()=>e(o)},ue.createElement("span",{className:"glyphicon glyphicon-trash"}),ue.createElement("span",{className:"sr-only"},"Remove")))))})),o=this.state.serviceDiscoveryRegistriesAvailable.length?ue.createElement("button",{className:"btn btn-block btn-sm add-new",onClick:this.pushServiceDiscoveryAssociation},ue.createElement("span",{className:"glyphicon glyphicon-plus-sign"}),"Add New Service Registry"):ue.createElement("div",{className:"sm-label-left"},ue.createElement(he,{color:"warning"},"No registries found in the selected account/region/VPC"));return ue.createElement("div",{className:"container-fluid form-horizontal"},ue.createElement("div",{className:"form-group"},ue.createElement("div",{className:"sm-label-left"},ue.createElement("b",null,"Service Registries (optional)"),ue.createElement(R,{id:"ecs.serviceDiscovery"})),ue.createElement("form",{name:"ecsServiceDiscoveryRegistryMappings"},ue.createElement("table",{className:"table table-condensed packed tags"},ue.createElement("thead",null,ue.createElement("tr",null,i&&ue.createElement("th",{style:{width:"30%"}},"Container name",ue.createElement(R,{id:"ecs.serviceDiscoveryContainerName"})),i?ue.createElement("th",{style:{width:"55%"}},"Registry",ue.createElement(R,{id:"ecs.serviceDiscoveryRegistry"})):ue.createElement("th",{style:{width:"80%"}},"Registry",ue.createElement(R,{id:"ecs.serviceDiscoveryRegistry"})),ue.createElement("th",{style:{width:"15%"}},"Port",ue.createElement(R,{id:"ecs.serviceDiscoveryContainerPort"})),ue.createElement("th",null))),ue.createElement("tbody",null,s),ue.createElement("tfoot",null,ue.createElement("tr",null,ue.createElement("td",{colSpan:4},o)))))))}}const pt="spinnaker.ecs.serverGroup.configure.wizard.serviceDiscovery.react";t(pt,[]).component("serviceDiscoveryReact",fe($(dt,"serviceDiscoveryReact"),["command","notifyAngular","configureCommand"]));class ut extends ue.Component{constructor(e){super(e),this.getIdToImageMap=()=>{const e=new Map;return this.props.command.backingData.filtered.images.forEach((t=>{e.set(t.imageId,t)})),e},this.getEmptyImageDescription=()=>({imageId:"",message:"",fromTrigger:!1,fromContext:!1,stageId:"",imageLabelOrSha:"",account:"",registry:"",repository:"",tag:""}),this.excludedArtifactTypePatterns=[B.KUBERNETES,B.DOCKER_IMAGE,B.FRONT50_PIPELINE_TEMPLATE],this.onExpectedArtifactSelected=e=>{const t={artifactId:e};this.props.notifyAngular("taskDefinitionArtifact",t),this.setState({taskDefArtifact:t})},this.onArtifactEdited=e=>{const t={artifact:e};this.props.notifyAngular("taskDefinitionArtifact",t),this.setState({taskDefArtifact:t})},this.pushMapping=()=>{const e=this.state.containerMappings;e.push({containerName:"",imageDescription:this.getEmptyImageDescription()}),this.setState({containerMappings:e})},this.pushTargetGroupMapping=()=>{const e=this.state.targetGroupMappings;e.push({containerName:"",targetGroup:"",containerPort:80}),this.setState({targetGroupMappings:e})},this.updateContainerMappingName=(e,t)=>{const n=this.state.containerMappings;n[e].containerName=t,this.props.notifyAngular("containerMappings",n),this.setState({containerMappings:n})},this.updateContainerMappingImage=(e,t)=>{let n=this.getIdToImageMap().get(t.value);n||(n=this.getEmptyImageDescription());const a=this.state.containerMappings;a[e].imageDescription=n,this.props.notifyAngular("containerMappings",a),this.setState({containerMappings:a})},this.updateTargetGroupMappingTargetGroup=(e,t)=>{const n=this.state.targetGroupMappings;n[e].targetGroup=t.value,this.props.notifyAngular("targetGroupMappings",n),this.setState({targetGroupMappings:n})},this.updateTargetGroupMappingContainer=(e,t)=>{const n=this.state.targetGroupMappings;n[e].containerName=t,this.props.notifyAngular("targetGroupMappings",n),this.setState({targetGroupMappings:n})},this.updateTargetGroupMappingPort=(e,t)=>{const n=this.state.targetGroupMappings;n[e].containerPort=t,this.props.notifyAngular("targetGroupMappings",n),this.setState({targetGroupMappings:n})},this.removeMapping=e=>{const t=this.state.containerMappings;t.splice(e,1),this.props.notifyAngular("containerMappings",t),this.setState({containerMappings:t})},this.removeTargetGroupMapping=e=>{const t=this.state.targetGroupMappings;t.splice(e,1),this.props.notifyAngular("targetGroupMappings",t),this.setState({targetGroupMappings:t})},this.updateEvaluateTaskDefArtifactFlag=()=>{this.props.notifyAngular("evaluateTaskDefinitionArtifactExpressions",!this.props.command.evaluateTaskDefinitionArtifactExpressions),this.setState({evaluateTaskDefinitionArtifactExpressions:!this.props.command.evaluateTaskDefinitionArtifactExpressions})};const t=this.props.command;let n="";t.containerMappings&&t.containerMappings.length>0&&(n=t.containerMappings[0].containerName);let a=[];t.targetGroupMappings&&t.targetGroupMappings.length>0&&(a=t.targetGroupMappings),t.targetGroup&&t.targetGroup.length>0&&(a.push({containerName:t.loadBalancedContainer||n,targetGroup:t.targetGroup,containerPort:t.containerPort}),t.targetGroup="",t.loadBalancedContainer=""),t.targetGroupMappings=re(a,W),this.state={taskDefArtifact:t.taskDefinitionArtifact,containerMappings:t.containerMappings?t.containerMappings:[],targetGroupMappings:t.targetGroupMappings,targetGroupsAvailable:t.backingData&&t.backingData.filtered?t.backingData.filtered.targetGroups:[],dockerImages:t.backingData&&t.backingData.filtered?t.backingData.filtered.images:[],loadBalancedContainer:t.loadBalancedContainer||n,taskDefArtifactAccount:t.taskDefinitionArtifactAccount,evaluateTaskDefinitionArtifactExpressions:t.evaluateTaskDefinitionArtifactExpressions}}componentDidMount(){this.props.configureCommand("1").then((()=>{this.setState({dockerImages:this.props.command.backingData.filtered.images,targetGroupsAvailable:this.props.command.backingData.filtered.targetGroups})}))}render(){const{command:e}=this.props,t=this.removeMapping,n=this.removeTargetGroupMapping,a=this.updateContainerMappingName,r=this.updateContainerMappingImage,i=this.updateTargetGroupMappingContainer,s=this.updateTargetGroupMappingTargetGroup,o=this.updateTargetGroupMappingPort,l=this.updateEvaluateTaskDefArtifactFlag,c=this.state.dockerImages.map((function(e){let t="";return(e.fromTrigger||e.fromContext)&&(t=e.fromTrigger?"(TRIGGER) ":"(FIND IMAGE RESULT) "),{label:`${t} (${e.imageId})`,value:e.imageId}})),d=this.state.targetGroupsAvailable.map((function(e){return{label:`${e}`,value:e}})),p=this.state.containerMappings.map((function(e,n){return ue.createElement("tr",{key:n},ue.createElement("td",null,ue.createElement("input",{"data-test-id":"Artifacts.containerName",className:"form-control input-sm",required:!0,placeholder:"enter container name...",value:e.containerName.toString(),onChange:e=>a(n,e.target.value)})),ue.createElement("td",{"data-test-id":"Artifacts.containerImage"},ue.createElement(M,{placeholder:"Select an image to use...",options:c,value:e.imageDescription.imageId,onChange:e=>{r(n,e)},clearable:!1})),ue.createElement("td",null,ue.createElement("div",{className:"form-control-static"},ue.createElement("a",{className:"btn-link sm-label","data-test-id":"Artifacts.containerRemove",onClick:()=>t(n)},ue.createElement("span",{className:"glyphicon glyphicon-trash"}),ue.createElement("span",{className:"sr-only"},"Remove")))))})),u=this.state.targetGroupMappings.map((function(e,t){return ue.createElement("tr",{key:t},ue.createElement("td",null,ue.createElement("input",{"data-test-id":"Artifacts.targetGroupContainer",className:"form-control input-sm",required:!0,placeholder:"Enter a container name ...",value:e.containerName.toString(),onChange:e=>i(t,e.target.value)})),ue.createElement("td",{"data-test-id":"Artifacts.targetGroup"},ue.createElement(M,{placeholder:"Select a target group to use...",options:d,value:e.targetGroup.toString(),onChange:e=>s(t,e),clearable:!1})),ue.createElement("td",null,ue.createElement("input",{"data-test-id":"Artifacts.targetGroupPort",type:"number",className:"form-control input-sm no-spel",required:!0,value:e.containerPort.toString(),onChange:e=>o(t,e.target.valueAsNumber)})),ue.createElement("td",null,ue.createElement("div",{className:"form-control-static"},ue.createElement("a",{className:"btn-link sm-label","data-test-id":"Artifacts.targetGroupRemove",onClick:()=>n(t)},ue.createElement("span",{className:"glyphicon glyphicon-trash"}),ue.createElement("span",{className:"sr-only"},"Remove")))))})),m=this.state.targetGroupsAvailable.length?ue.createElement("button",{className:"btn btn-block btn-sm add-new","data-test-id":"Artifacts.targetGroupAdd",onClick:this.pushTargetGroupMapping},ue.createElement("span",{className:"glyphicon glyphicon-plus-sign"}),"Add New Target Group Mapping"):ue.createElement("div",{className:"sm-label-left"},ue.createElement(he,{color:"warning"},"No target groups found in the selected account/region/VPC"));return ue.createElement("div",{className:"container-fluid form-horizontal"},ue.createElement("div",{className:"form-group"},ue.createElement("div",{className:"col-md-12"},ue.createElement(F,{artifact:this.state.taskDefArtifact.artifact,excludedArtifactTypePatterns:this.excludedArtifactTypePatterns,expectedArtifactId:this.state.taskDefArtifact.artifactId,label:"Artifact",helpKey:"ecs.taskDefinitionArtifact",onExpectedArtifactSelected:e=>this.onExpectedArtifactSelected(e.id),onArtifactEdited:this.onArtifactEdited,pipeline:e.viewState.pipeline,stage:e.viewState.currentStage}))),ue.createElement(L,{groupClassName:"form-group evaluateTaskDef",label:"Expression Evaluation",helpKey:"ecs.evaluateExpression",labelColumns:5,fieldColumns:7},ue.createElement(O,{checked:!0===e.evaluateTaskDefinitionArtifactExpressions,onChange:()=>{l()},text:"Evaluate SpEL expressions in artifact"})),ue.createElement("div",{className:"form-group"},ue.createElement("div",{className:"sm-label-left"},ue.createElement("b",null,"Container Mappings"),ue.createElement(R,{id:"ecs.containerMappings"})),ue.createElement("form",{name:"ecsTaskDefinitionContainerMappings"},ue.createElement("table",{className:"table table-condensed packed tags"},ue.createElement("thead",null,ue.createElement("tr",{key:"header"},ue.createElement("th",{style:{width:"30%"}},"Container name",ue.createElement(R,{id:"ecs.containerMappingName"})),ue.createElement("th",{style:{width:"70%"}},"Container image",ue.createElement(R,{id:"ecs.containerMappingImage"})),ue.createElement("th",null))),ue.createElement("tbody",null,p),ue.createElement("tfoot",null,ue.createElement("tr",null,ue.createElement("td",{colSpan:3},ue.createElement("button",{className:"btn btn-block btn-sm add-new","data-test-id":"Artifacts.containerAdd",onClick:this.pushMapping},ue.createElement("span",{className:"glyphicon glyphicon-plus-sign"}),"Add New Container Mapping"))))))),ue.createElement("div",{className:"form-group"},ue.createElement("div",{className:"sm-label-left"},ue.createElement("b",null,"Target Group Mappings"),ue.createElement(R,{id:"ecs.targetGroupMappings"})),ue.createElement("form",{name:"ecsTaskDefinitionTargetGroupMappings"},ue.createElement("table",{className:"table table-condensed packed tags"},ue.createElement("thead",null,ue.createElement("tr",{key:"header"},ue.createElement("th",{style:{width:"30%"}},"Container name",ue.createElement(R,{id:"ecs.loadBalancedContainer"})),ue.createElement("th",{style:{width:"55%"}},"Target group",ue.createElement(R,{id:"ecs.loadBalancer.targetGroup"})),ue.createElement("th",{style:{width:"15%"}},"Target port",ue.createElement(R,{id:"ecs.loadbalancing.targetPort"})),ue.createElement("th",null))),ue.createElement("tbody",null,u),ue.createElement("tfoot",null,ue.createElement("tr",null,ue.createElement("td",{colSpan:4},m)))))))}}const mt="spinnaker.ecs.serverGroup.configure.wizard.taskDefinition.react";t(mt,[]).component("taskDefinitionReact",fe($(ut,"taskDefinitionReact"),["command","notifyAngular","configureCommand"]));const gt="spinnaker.ecs.serverGroup.resize";t(gt,[]).component("ecsResizeCapacity",{bindings:{command:"=",currentSize:"="},templateUrl:"ecs/src/serverGroup/details/resize/resizeCapacity.component.html",controller:()=>{}}),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/serverGroup/details/resize/resizeCapacity.component.html",'<div ng-if="$ctrl.command.advancedMode">\n <div class="form-group">\n <div class="col-md-12">\n <p>Sets up auto-scaling for this server group.</p>\n <p>To disable auto-scaling, use the <a href ng-click="$ctrl.command.advancedMode = false">Simple Mode</a>.</p>\n </div>\n </div>\n <div class="form-group">\n <div class="col-md-2 col-md-offset-3"><b>Min</b></div>\n <div class="col-md-2"><b>Max</b></div>\n <div class="col-md-2"><b>Desired</b></div>\n </div>\n <div class="form-group">\n <div class="col-md-3 sm-label-right">Current</div>\n <div class="col-md-2">\n <input type="number" class="form-control input-sm" ng-model="$ctrl.currentSize.min" readonly />\n </div>\n <div class="col-md-2">\n <input type="number" class="form-control input-sm" ng-model="$ctrl.currentSize.max" readonly />\n </div>\n <div class="col-md-2">\n <input type="number" class="form-control input-sm" ng-model="$ctrl.currentSize.desired" readonly />\n </div>\n </div>\n <div class="form-group">\n <div class="col-md-3 sm-label-right">Resize to</div>\n <div class="col-md-2">\n <input\n type="number"\n class="form-control input-sm"\n ng-model="$ctrl.command.min"\n min="0"\n required\n max="{{ $ctrl.command.max }}"\n />\n </div>\n <div class="col-md-2">\n <input\n type="number"\n class="form-control input-sm"\n ng-model="$ctrl.command.max"\n required\n min="{{ $ctrl.command.min }}"\n />\n </div>\n <div class="col-md-2">\n <input\n type="number"\n class="form-control input-sm"\n ng-model="$ctrl.command.desired"\n required\n min="{{ $ctrl.command.min }}"\n max="{{ $ctrl.command.max }}"\n />\n </div>\n </div>\n</div>\n<div ng-if="!$ctrl.command.advancedMode">\n <div class="form-group">\n <div class="col-md-12">\n <p>\n To modify min and max instance counts, use the\n <a href ng-click="$ctrl.command.advancedMode = true">Advanced Mode</a>.\n </p>\n </div>\n </div>\n <div class="form-group form-inline">\n <div class="col-md-3 sm-label-right">Current size</div>\n <div class="col-md-6">\n <input\n type="number"\n class="form-control input-sm"\n ng-model="$ctrl.currentSize.desired"\n style="width: 60px"\n readonly\n />\n instance<span ng-if="$ctrl.currentSize.desired > 1">s</span>\n </div>\n </div>\n <div class="form-group form-inline">\n <div class="col-md-3 sm-label-right">Resize to</div>\n <div class="col-md-6">\n <input\n type="number"\n class="form-control input-sm highlight-pristine"\n ng-model="$ctrl.command.newSize"\n min="0"\n required\n style="width: 60px"\n />\n instances\n </div>\n </div>\n</div>\n')}]);const vt="spinnaker.ecs.serverGroup.details.resize.controller";e.module(vt,[N,gt]).controller("ecsResizeServerGroupCtrl",["$scope","$uibModalInstance","serverGroupWriter","application","serverGroup",function(t,n,a,r,i){t.serverGroup=i,t.currentSize={min:i.capacity.min,max:i.capacity.max,desired:i.capacity.desired,newSize:null},t.verification={},t.command=e.copy(t.currentSize),t.command.advancedMode=i.capacity.min!==i.capacity.max,r&&r.attributes&&(r.attributes.platformHealthOnlyShowOverride&&r.attributes.platformHealthOnly&&(t.command.interestingHealthProviderNames=["Ecs"]),t.command.platformHealthOnlyShowOverride=r.attributes.platformHealthOnlyShowOverride),this.isValid=function(){const e=t.command;return!!t.verification.verified&&(e.advancedMode?e.min<=e.max&&e.desired>=e.min&&e.desired<=e.max:null!==e.newSize)},t.taskMonitor=new z({application:r,title:"Resizing "+i.name,modalInstance:n}),this.resize=function(){if(!this.isValid())return;let e={min:t.command.min,max:t.command.max,desired:t.command.desired};t.command.advancedMode||(e={min:t.command.newSize,max:t.command.newSize,desired:t.command.newSize});t.taskMonitor.submit((function(){return a.resizeServerGroup(i,r,{capacity:e,interestingHealthProviderNames:t.command.interestingHealthProviderNames,reason:t.command.reason})}))},this.cancel=function(){n.dismiss()}}]);const ht="spinnaker.ecs.serverGroup.details.rollback.controller";t(ht,[N]).controller("ecsRollbackServerGroupCtrl",["$scope","$uibModalInstance","serverGroupWriter","application","serverGroup","disabledServerGroups","allServerGroups",function(e,t,n,a,r,i,s){e.serverGroup=r,e.disabledServerGroups=i.sort(((e,t)=>t.name.localeCompare(e.name))),e.allServerGroups=s.sort(((e,t)=>t.name.localeCompare(e.name))),e.verification={},e.command={rollbackType:"EXPLICIT",rollbackContext:{rollbackServerGroupName:r.name}},a&&a.attributes&&(a.attributes.platformHealthOnlyShowOverride&&a.attributes.platformHealthOnly&&(e.command.interestingHealthProviderNames=["Ecs"]),e.command.platformHealthOnlyShowOverride=a.attributes.platformHealthOnlyShowOverride),this.isValid=function(){const t=e.command;return!!e.verification.verified&&void 0!==t.rollbackContext.restoreServerGroupName},e.taskMonitor=new z({application:a,title:"Rollback "+r.name,modalInstance:t}),this.rollback=function(){if(!this.isValid())return;e.taskMonitor.submit((function(){return n.rollbackServerGroup(r,a,e.command)}))},this.cancel=function(){t.dismiss()},this.label=function(e){return e?e.buildInfo&&e.buildInfo.jenkins&&e.buildInfo.jenkins.number?e.name+" (build #"+e.buildInfo.jenkins.number+")":e.name:""},this.group=function(e){return e.isDisabled?"Disabled Server Groups":"Enabled Server Groups"}}]);const ft="spinnaker.ecs.serverGroup.transformer";t(ft,[]).service("ecsServerGroupTransformer",class{addComparator(e){if(e.comparisonOperator)switch(e.comparisonOperator){case"LessThanThreshold":e.comparator="<";break;case"GreaterThanThreshold":e.comparator=">";break;case"LessThanOrEqualToThreshold":e.comparator="≤";break;case"GreaterThanOrEqualToThreshold":e.comparator="≥"}}addAdjustmentAttributes(e){e.operator=e.scalingAdjustment<0?"decrease":"increase",e.absAdjustment=Math.abs(e.scalingAdjustment)}transformScalingPolicy(e){const t={...e},n=(e,t)=>t.metricIntervalUpperBound-e.metricIntervalUpperBound,a=(e,t)=>e.metricIntervalLowerBound-t.metricIntervalLowerBound;if(t.alarms=e.alarms||[],t.alarms.forEach((e=>this.addComparator(e))),this.addAdjustmentAttributes(t),t.stepAdjustments&&t.stepAdjustments.length){t.stepAdjustments.forEach((e=>this.addAdjustmentAttributes(e)));const r=e.stepAdjustments.every((e=>void 0!==e.metricIntervalUpperBound))?n:a;t.stepAdjustments.sort(((e,t)=>r(e,t)))}return t}normalizeServerGroupDetails(e){const t={...e};return e.scalingPolicies&&(t.scalingPolicies=e.scalingPolicies.map((e=>this.transformScalingPolicy(e)))),t}normalizeServerGroup(e){return e.instances.forEach((t=>{t.vpcId=e.vpcId})),de.listVpcs().then((t=>this.addVpcNameToServerGroup(e)(t)))}addVpcNameToServerGroup(e){return t=>{const n=t.find((t=>t.id===e.vpcId));return e.vpcName=n?n.name:"",e}}convertServerGroupCommandToDeployConfiguration(e){const t=ie({backingData:[],viewState:[]},e);return t.cloudProvider="ecs",t.availabilityZones={},t.availabilityZones[t.region]=e.availabilityZones,t.loadBalancers=(e.loadBalancers||[]).concat(e.vpcLoadBalancers||[]),t.targetGroup=e.targetGroup||"",t.account=t.credentials,t.subnetType=t.subnetType||"","clone"!==e.viewState.mode&&delete t.source,delete t.region,delete t.viewState,delete t.backingData,delete t.selectedProvider,delete t.instanceProfile,delete t.vpcId,t}});const yt="spinnaker.ecs.serverGroup.details.controller";e.module(yt,[V,ft,P,N,Xe,vt,ht]).controller("ecsServerGroupDetailsCtrl",["$scope","$state","app","serverGroup","ecsServerGroupCommandBuilder","$uibModal","serverGroupWriter","ecsServerGroupTransformer","overrideRegistry",function(t,n,a,r,i,o,l,c,d){this.state={loading:!0},this.firewallsLabel=C.get("Firewalls"),this.application=a;const p=()=>{t.$$destroyed||n.go("^",{allowModalToStayOpen:!0},{location:"replace"})},u=()=>{this.state.loading=!1},m=()=>a.ready().then((()=>{let e=Q(a.serverGroups.data,(e=>e.name===r.name&&e.account===r.accountId&&e.region===r.region));return e||a.loadBalancers.data.some((t=>{if(t.account===r.accountId&&t.region===r.region)return t.serverGroups.some((t=>{if(t.name===r.name)return e=t,!0}))})),e})).then((t=>q.getServerGroup(a.name,r.accountId,r.region,r.name).then((n=>{if(u(),e.extend(n,t,{account:r.accountId}),this.serverGroup=c.normalizeServerGroupDetails(n),this.applyAccountDetails(this.serverGroup),oe(this.serverGroup))p();else{this.image=n.image?n.image:void 0;const e=this.serverGroup.asg?this.serverGroup.asg.vpczoneIdentifier:"";if(""!==e){const t=e.split(",")[0];G.listSubnets().then((e=>{const n=X(e).find({id:t}).value();this.serverGroup.subnetType=n.purpose}))}if(n.image&&n.image.description){n.image.description.split(", ").forEach((e=>{const t=e.split("=");2===t.length&&"ancestor_name"===t[0]&&(n.image.baseImage=t[1])}))}if(n.image&&n.image.tags){const e=n.image.tags.find((e=>"base_ami_version"===e.key));e&&(n.baseAmiVersion=e.value)}this.scalingPolicies=this.serverGroup.scalingPolicies,K(this.serverGroup,"buildInfo.jenkins")&&(this.changeConfig.buildInfo={jenkins:this.serverGroup.buildInfo.jenkins})}})))).catch(p);m().then((()=>{t.$$destroyed||a.serverGroups.onRefresh(t,m)})),this.destroyServerGroup=()=>{const e=this.serverGroup,t={application:a,title:"Destroying "+e.name,onTaskComplete:()=>{n.includes("**.serverGroup",r)&&n.go("^")}},r={name:e.name,accountId:e.account,region:e.region},i={header:"Really destroy "+e.name+"?",buttonText:"Destroy "+e.name,account:e.account,taskMonitorConfig:t,submitMethod:t=>l.destroyServerGroup(e,a,t),askForReason:!0,platformHealthOnlyShowOverride:a.attributes.platformHealthOnlyShowOverride,platformHealthType:"Ecs"};U.addDestroyWarningMessage(a,e,i),a.attributes.platformHealthOnlyShowOverride&&a.attributes.platformHealthOnly&&(i.interestingHealthProviderNames=["Ecs"]),s.confirm(i)},this.disableServerGroup=()=>{const e=this.serverGroup,t={application:a,title:"Disabling "+e.name},n={header:"Really disable "+e.name+"?",buttonText:"Disable "+e.name,account:e.account,taskMonitorConfig:t,platformHealthOnlyShowOverride:a.attributes.platformHealthOnlyShowOverride,platformHealthType:"Ecs",submitMethod:t=>l.disableServerGroup(e,a,t),askForReason:!0};U.addDisableWarningMessage(a,e,n),a.attributes.platformHealthOnlyShowOverride&&a.attributes.platformHealthOnly&&(n.interestingHealthProviderNames=["Ecs"]),s.confirm(n)},this.enableServerGroup=()=>{const e=this.serverGroup,t={application:a,title:"Enabling "+e.name},n={header:"Really enable "+e.name+"?",buttonText:"Enable "+e.name,account:e.account,taskMonitorConfig:t,platformHealthOnlyShowOverride:a.attributes.platformHealthOnlyShowOverride,platformHealthType:"Ecs",submitMethod:t=>l.enableServerGroup(e,a,t),askForReason:!0};a.attributes.platformHealthOnlyShowOverride&&a.attributes.platformHealthOnly&&(n.interestingHealthProviderNames=["Ecs"]),s.confirm(n)},this.rollbackServerGroup=()=>{o.open({templateUrl:d.getTemplate("ecs.rollback.modal","ecs/src/serverGroup/details/rollback/rollbackServerGroup.html"),windowClass:"modal-z-index",controller:"ecsRollbackServerGroupCtrl as ctrl",resolve:{serverGroup:()=>this.serverGroup,disabledServerGroups:()=>{const e=Q(a.clusters,{name:this.serverGroup.cluster,account:this.serverGroup.account});return se(e.serverGroups,{isDisabled:!0,region:this.serverGroup.region})},allServerGroups:()=>a.getDataSource("serverGroups").data.filter((e=>e.cluster===this.serverGroup.cluster&&e.region===this.serverGroup.region&&e.account===this.serverGroup.account&&e.name!==this.serverGroup.name)),application:()=>a}})},this.resizeServerGroup=()=>{o.open({templateUrl:d.getTemplate("ecs.resize.modal","ecs/src/serverGroup/details/resize/resizeServerGroup.html"),controller:"ecsResizeServerGroupCtrl as ctrl",windowClass:"modal-z-index",resolve:{serverGroup:()=>this.serverGroup,application:()=>a}})},this.cloneServerGroup=e=>{o.open({templateUrl:"ecs/src/serverGroup/configure/wizard/serverGroupWizard.html",controller:"ecsCloneServerGroupCtrl as ctrl",size:"lg",windowClass:"modal-z-index",resolve:{title:()=>"Clone "+e.name,application:()=>a,serverGroupCommand:()=>i.buildServerGroupCommandFromExisting(a,e)}})},this.buildJenkinsLink=()=>{if(K(this,"serverGroup.buildInfo.buildInfoUrl"))return this.serverGroup.buildInfo.buildInfoUrl;if(K(this,"serverGroup.buildInfo.jenkins")){const e=this.serverGroup.buildInfo.jenkins;return e.host+"job/"+e.name+"/"+e.number}return null},this.truncateCommitHash=()=>this.serverGroup&&this.serverGroup.buildInfo&&this.serverGroup.buildInfo.commit?this.serverGroup.buildInfo.commit.substring(0,8):null,this.applyAccountDetails=e=>f.getAccountDetails(e.account).then((t=>{e.accountDetails=t}))}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/serverGroup/details/rollback/rollbackServerGroup.html",'<div modal-page class="confirmation-modal">\n <task-monitor monitor="taskMonitor"></task-monitor>\n <form role="form">\n <modal-close dismiss="$dismiss()"></modal-close>\n <div class="modal-header">\n <h4 class="modal-title">Rollback {{serverGroup.name}}</h4>\n </div>\n <div class="modal-body confirmation-modal">\n <div class="row">\n <div class="col-sm-3 sm-label-right">Restore to</div>\n <div class="col-sm-6">\n <ui-select ng-model="command.rollbackContext.restoreServerGroupName" class="form-control input-sm">\n <ui-select-match placeholder="Select...">{{ctrl.label($select.selected)}}</ui-select-match>\n <ui-select-choices group-by="ctrl.group" repeat="serverGroup.name as serverGroup in allServerGroups">\n <span ng-bind-html="ctrl.label(serverGroup)"></span>\n </ui-select-choices>\n </ui-select>\n </div>\n </div>\n\n <div class="row" ng-if="command.platformHealthOnlyShowOverride">\n <div class="col-sm-10 col-sm-offset-1">\n <platform-health-override\n command="command"\n platform-health-type="\'Ecs\'"\n show-help-details="true"\n field-columns="12"\n >\n </platform-health-override>\n </div>\n </div>\n\n <task-reason command="command"></task-reason>\n\n <div class="row">\n <div class="col-sm-4 sm-label-right">Rollback Operations</div>\n </div>\n <div class="row">\n <div class="col-sm-11 col-sm-offset-1">\n <ol>\n <li>Enable <em>{{ command.rollbackContext.restoreServerGroupName || \'previous server group\' }}</em></li>\n <li>\n Resize <em>{{ command.rollbackContext.restoreServerGroupName || \'previous server group\' }}</em> to [\n <strong>min</strong>: {{serverGroup.capacity.desired}}, <strong>max</strong>: {{ serverGroup.capacity.max\n }}, <strong>desired</strong>: {{ serverGroup.capacity.desired }} ]<br />(minimum capacity pinned at\n {{serverGroup.capacity.desired}} to prevent autoscaling down during rollback)\n </li>\n <li>Disable {{ serverGroup.name }}</li>\n <li>\n Restore minimum capacity of\n <em>{{ command.rollbackContext.restoreServerGroupName || \'previous server group\' }}</em> [\n <strong>min</strong>: {{ serverGroup.capacity.min }} ]\n </li>\n </ol>\n <p>This rollback will affect server groups in {{ serverGroup.account }} ({{ serverGroup.region }}).</p>\n </div>\n </div>\n </div>\n <ecs-footer\n action="ctrl.rollback()"\n cancel="ctrl.cancel()"\n is-valid="ctrl.isValid()"\n account="serverGroup.account"\n verification="verification"\n ></ecs-footer>\n </form>\n</div>\n')}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/serverGroup/details/resize/resizeServerGroup.html",'<div modal-page class="confirmation-modal">\n <task-monitor monitor="taskMonitor"></task-monitor>\n <form role="form">\n <modal-close dismiss="$dismiss()"></modal-close>\n <div class="modal-header">\n <h4 class="modal-title">Resize {{serverGroup.name}}</h4>\n </div>\n <div class="modal-body confirmation-modal">\n <div class="form-horizontal">\n <ecs-resize-capacity command="command" current-size="currentSize"></ecs-resize-capacity>\n </div>\n <div class="row" ng-if="command.platformHealthOnlyShowOverride">\n <div class="col-sm-10 col-sm-offset-1">\n <platform-health-override command="command" platform-health-type="\'Ecs\'" show-help-details="true">\n </platform-health-override>\n </div>\n </div>\n <task-reason command="command"></task-reason>\n </div>\n <ecs-footer\n action="ctrl.resize()"\n cancel="ctrl.cancel()"\n is-valid="ctrl.isValid()"\n account="serverGroup.account"\n verification="verification"\n ></ecs-footer>\n </form>\n</div>\n')}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/serverGroup/configure/wizard/serverGroupWizard.html",'<form name="form" class="form-horizontal" novalidate>\n <div ng-if="state.requiresTemplateSelection">\n <ng-include src="pages.templateSelection"></ng-include>\n </div>\n <div ng-if="!state.loaded" style="height: 200px">\n <h3 us-spinner="{radius:30, width:8, length: 16}"></h3>\n </div>\n <div ng-if="!state.requiresTemplateSelection">\n <v2-modal-wizard ng-show="state.loaded" heading="{{title}}" task-monitor="taskMonitor" dismiss="$dismiss()">\n <v2-wizard-page key="basicSettings" label="Basic Settings" mark-complete-on-view="false" done="true">\n <ng-include src="pages.basicSettings"></ng-include>\n </v2-wizard-page>\n <v2-wizard-page key="networking" label="Networking" done="true">\n <ng-include src="pages.networking"></ng-include>\n </v2-wizard-page>\n <v2-wizard-page key="taskDefinition" label="Task Definition" done="true">\n <ng-include src="pages.taskDefinition"></ng-include>\n </v2-wizard-page>\n <div ng-if="!command.useTaskDefinitionArtifact">\n <v2-wizard-page key="container" label="Container" done="true">\n <ng-include src="pages.container"></ng-include>\n </v2-wizard-page>\n </div>\n <v2-wizard-page key="horizontalScaling" label="Horizontal Scaling" done="true">\n <ng-include src="pages.horizontalScaling"></ng-include>\n </v2-wizard-page>\n <div ng-if="!command.useTaskDefinitionArtifact">\n <v2-wizard-page key="logging" label="Logging" done="true">\n <ng-include src="pages.logging"></ng-include>\n </v2-wizard-page>\n </div>\n <v2-wizard-page key="serviceDiscovery" label="Service Discovery" done="true">\n <ng-include ng-if="!command.useTaskDefinitionArtifact" src="pages.serviceDiscovery"></ng-include>\n <ng-include ng-if="command.useTaskDefinitionArtifact" src="pages.serviceDiscovery"></ng-include>\n </v2-wizard-page>\n <v2-wizard-page key="advanced" label="Advanced Settings" mark-complete-on-view="false" done="true">\n <ng-include src="pages.advancedSettings"></ng-include>\n </v2-wizard-page>\n </v2-modal-wizard>\n <div class="modal-footer" ng-if="state.loaded">\n <button ng-disabled="taskMonitor.submitting" class="btn btn-default btn-cancel" ng-click="ctrl.cancel()">\n Cancel\n </button>\n <submit-button\n data-test-id="ServerGroupWizard.submitButton"\n ng-if="ctrl.showSubmitButton()"\n is-disabled="!ctrl.isValid() || taskMonitor.submitting"\n label="command.viewState.submitButtonLabel"\n submitting="taskMonitor.submitting"\n on-click="ctrl.submit()"\n is-new="true"\n ></submit-button>\n </div>\n </div>\n</form>\n')}]);const bt="spinnaker.ecs.serverGroup.details";t(bt,[yt]);class St{static getEvents(e){return r("/applications").path(e.app,"serverGroups",e.account,e.name,"events").query({region:e.region,provider:e.cloudProvider}).get().catch((e=>(ye.error(e,"error retrieving events"),[])))}}class kt{constructor(e,t){this.$uibModalInstance=e,this.serverGroup=t,this.events=[]}$onInit(){this.viewState={loading:!0,error:!1},St.getEvents(this.serverGroup).then((e=>{this.viewState.loading=!1,this.events=e}),(()=>{this.viewState.error=!0}))}close(){this.$uibModalInstance.close()}}kt.$inject=["$uibModalInstance","serverGroup"];const Ct="spinnaker.ecs.serverGroup.events.controller";t(Ct,[]).controller("EventsController",kt);class wt{constructor(e){this.$uibModal=e}showEvents(){this.$uibModal.open({templateUrl:"ecs/src/serverGroup/events/events.html",controller:kt,controllerAs:"$ctrl",windowClass:"modal-z-index",resolve:{serverGroup:()=>this.serverGroup}})}}wt.$inject=["$uibModal"];const Et={bindings:{serverGroup:"<"},controller:wt,template:'<a href ng-click="$ctrl.showEvents()">View Events</a>'},Dt="spinnaker.ecs.serverGroup.details.viewEvents.link";t(Dt,[Ct]).component("viewEventsLink",Et),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/serverGroup/events/events.html",'<div modal-page>\n <modal-close dismiss="$ctrl.close()"></modal-close>\n <div class="modal-header">\n <h4 class="modal-title">Server Group Events for {{$ctrl.serverGroup.name}}</h4>\n </div>\n <div class="modal-body">\n <div class="loading" ng-if="$ctrl.viewState.loading">\n <loading-spinner size="\'small\'"></loading-spinner>\n </div>\n <div ng-if="$ctrl.viewState.error" class="text-center">\n <p>There was an error loading events for {{$ctrl.serverGroup.name}}. Please try again later.</p>\n </div>\n <div ng-if="!$ctrl.viewState.loading && !$ctrl.viewState.error && !$ctrl.events.length" class="text-center">\n <p>No scaling events found for {{$ctrl.serverGroup.name}}.</p>\n </div>\n\n <div ng-repeat="event in $ctrl.events" ng-if="!$ctrl.viewState.loading">\n <p class="clearfix"></p>\n <div ng-if="event.status === \'Success\'">\n <span class="label label-success pull-left">{{event.status}}</span>\n </div>\n <div ng-if="event.status !== \'Success\'">\n <span class="label label-{{event.status === \'Transition\' ? \'info\' : \'danger\'}} pull-left"\n >{{event.status}}</span\n >\n </div>\n\n <span class="label label-default pull-right">{{event.createdAt | timestamp}}</span>\n <div>{{event.message}}</div>\n <hr ng-if="!$last" />\n </div>\n </div>\n <div class="modal-footer">\n <button class="btn btn-primary" ng-click="$ctrl.close()">Close</button>\n </div>\n</div>\n')}]);const Gt="spinnaker.ecs.serverGroup";t(Gt,[Dt]);!function(e,t){void 0===t&&(t={});var n=t.insertAt;if(e&&"undefined"!=typeof document){var a=document.head||document.getElementsByTagName("head")[0],r=document.createElement("style");r.type="text/css","top"===n&&a.firstChild?a.insertBefore(r,a.firstChild):a.appendChild(r),r.styleSheet?r.styleSheet.cssText=e:r.appendChild(document.createTextNode(e))}}('.cloud-provider-logo .icon-ecs {\n -webkit-mask-image: url("data:image/svg+xml,%3Csvg id%3D%22Layer_1%22 data-name%3D%22Layer 1%22 xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22 width%3D%22100%22 height%3D%22100%22 viewBox%3D%220 0 100 100%22%3E %3Ctitle%3ECompute%3C%2Ftitle%3E %3Cg%3E %3Cpolygon points%3D%2219.64 22.51 16 24.32 16 75.68 19.64 77.49 33.98 51.07 19.64 22.51%22 fill%3D%22%239d5025%22%2F%3E %3Cpolygon points%3D%2230.72 31.78 36.08 24.19 60.1 34.87 54.5 35.76 30.72 31.78%22 fill%3D%22%239d5025%22%2F%3E %3Cpolygon points%3D%2226.56 68.77 32.46 76.88 60.1 64.95 54.76 64.12 26.56 68.77%22 fill%3D%22%239d5025%22%2F%3E %3Cpolygon points%3D%2228.12 75.5 19.64 77.49 19.64 22.51 28.12 24.44 28.12 75.5%22 fill%3D%22%23f58536%22%2F%3E %3Cpolygon points%3D%2223.66 20.5 28.12 18.27 36.52 53.56 28.12 81.73 23.66 79.5 23.66 20.5%22 fill%3D%22%239d5025%22%2F%3E %3Cpolygon points%3D%2254.46 64.08 60.1 64.95 65.26 50.58 60.1 34.87 54.46 35.76 54.46 64.08%22 fill%3D%22%239d5025%22%2F%3E %3Cpolygon points%3D%2236.8 79.28 28.12 81.73 28.12 18.27 36.8 20.73 36.8 79.28%22 fill%3D%22%23f58536%22%2F%3E %3Cpolygon points%3D%2266.01 63.84 28.12 70.88 28.12 81.73 66.01 71.03 66.01 63.84%22 fill%3D%22%23f58536%22%2F%3E %3Cpolygon points%3D%2266.08 36 28.12 28.79 28.12 18.27 66.08 29.04 66.08 36%22 fill%3D%22%23f58536%22%2F%3E %3Cpolygon points%3D%2260.1 27.34 66.19 29.02 66.19 71.03 60.1 72.7 60.1 27.34%22 fill%3D%22%23f58536%22%2F%3E %3Cpolygon points%3D%2284 44.45 67.7 45.22 61.94 44.83 78.42 31.55 84 44.45%22 fill%3D%22%236b3a19%22%2F%3E %3Cpolygon points%3D%2261.94 44.83 78.42 43.9 78.42 31.55 61.94 34.22 61.94 44.83%22 fill%3D%22%239d5025%22%2F%3E %3Cpolygon points%3D%2246.43 43.79 63.13 26.96 71.62 43.22 54.31 44.32 46.43 43.79%22 fill%3D%22%236b3a19%22%2F%3E %3Cpolygon points%3D%2246.43 43.79 63.13 42.37 63.13 26.96 46.43 30.87 46.43 43.79%22 fill%3D%22%239d5025%22%2F%3E %3Cpolygon points%3D%2261.94 55.39 84 55.77 78.42 68.67 61.94 66 61.94 55.39%22 fill%3D%22%239d5025%22%2F%3E %3Cpolygon points%3D%2246.43 56.43 71.62 57.01 63.13 73.26 46.43 69.36 46.43 56.43%22 fill%3D%22%239d5025%22%2F%3E %3Cpolygon points%3D%2246.43 56.43 63.13 57.86 71.62 57.01 54.31 55.9 46.43 56.43%22 fill%3D%22%23fbbf93%22%2F%3E %3Cpolygon points%3D%2284 55.77 67.7 55.01 61.94 55.39 78.42 56.33 84 55.77%22 fill%3D%22%23fbbf93%22%2F%3E %3Cpolygon points%3D%2278.42 43.9 84 44.45 84 33.22 78.42 31.55 78.42 43.9%22 fill%3D%22%23f58536%22%2F%3E %3Cpolygon points%3D%2271.62 43.22 63.13 42.37 63.13 26.96 71.62 29.51 71.62 43.22%22 fill%3D%22%23f58536%22%2F%3E %3Cpolygon points%3D%2278.42 56.33 84 55.77 84 67 78.42 68.67 78.42 56.33%22 fill%3D%22%23f58536%22%2F%3E %3Cpolygon points%3D%2271.62 57.01 63.13 57.86 63.13 73.26 71.62 70.72 71.62 57.01%22 fill%3D%22%23f58536%22%2F%3E %3C%2Fg%3E%3C%2Fsvg%3E");\n mask-image: url("data:image/svg+xml,%3Csvg id%3D%22Layer_1%22 data-name%3D%22Layer 1%22 xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22 width%3D%22100%22 height%3D%22100%22 viewBox%3D%220 0 100 100%22%3E %3Ctitle%3ECompute%3C%2Ftitle%3E %3Cg%3E %3Cpolygon points%3D%2219.64 22.51 16 24.32 16 75.68 19.64 77.49 33.98 51.07 19.64 22.51%22 fill%3D%22%239d5025%22%2F%3E %3Cpolygon points%3D%2230.72 31.78 36.08 24.19 60.1 34.87 54.5 35.76 30.72 31.78%22 fill%3D%22%239d5025%22%2F%3E %3Cpolygon points%3D%2226.56 68.77 32.46 76.88 60.1 64.95 54.76 64.12 26.56 68.77%22 fill%3D%22%239d5025%22%2F%3E %3Cpolygon points%3D%2228.12 75.5 19.64 77.49 19.64 22.51 28.12 24.44 28.12 75.5%22 fill%3D%22%23f58536%22%2F%3E %3Cpolygon points%3D%2223.66 20.5 28.12 18.27 36.52 53.56 28.12 81.73 23.66 79.5 23.66 20.5%22 fill%3D%22%239d5025%22%2F%3E %3Cpolygon points%3D%2254.46 64.08 60.1 64.95 65.26 50.58 60.1 34.87 54.46 35.76 54.46 64.08%22 fill%3D%22%239d5025%22%2F%3E %3Cpolygon points%3D%2236.8 79.28 28.12 81.73 28.12 18.27 36.8 20.73 36.8 79.28%22 fill%3D%22%23f58536%22%2F%3E %3Cpolygon points%3D%2266.01 63.84 28.12 70.88 28.12 81.73 66.01 71.03 66.01 63.84%22 fill%3D%22%23f58536%22%2F%3E %3Cpolygon points%3D%2266.08 36 28.12 28.79 28.12 18.27 66.08 29.04 66.08 36%22 fill%3D%22%23f58536%22%2F%3E %3Cpolygon points%3D%2260.1 27.34 66.19 29.02 66.19 71.03 60.1 72.7 60.1 27.34%22 fill%3D%22%23f58536%22%2F%3E %3Cpolygon points%3D%2284 44.45 67.7 45.22 61.94 44.83 78.42 31.55 84 44.45%22 fill%3D%22%236b3a19%22%2F%3E %3Cpolygon points%3D%2261.94 44.83 78.42 43.9 78.42 31.55 61.94 34.22 61.94 44.83%22 fill%3D%22%239d5025%22%2F%3E %3Cpolygon points%3D%2246.43 43.79 63.13 26.96 71.62 43.22 54.31 44.32 46.43 43.79%22 fill%3D%22%236b3a19%22%2F%3E %3Cpolygon points%3D%2246.43 43.79 63.13 42.37 63.13 26.96 46.43 30.87 46.43 43.79%22 fill%3D%22%239d5025%22%2F%3E %3Cpolygon points%3D%2261.94 55.39 84 55.77 78.42 68.67 61.94 66 61.94 55.39%22 fill%3D%22%239d5025%22%2F%3E %3Cpolygon points%3D%2246.43 56.43 71.62 57.01 63.13 73.26 46.43 69.36 46.43 56.43%22 fill%3D%22%239d5025%22%2F%3E %3Cpolygon points%3D%2246.43 56.43 63.13 57.86 71.62 57.01 54.31 55.9 46.43 56.43%22 fill%3D%22%23fbbf93%22%2F%3E %3Cpolygon points%3D%2284 55.77 67.7 55.01 61.94 55.39 78.42 56.33 84 55.77%22 fill%3D%22%23fbbf93%22%2F%3E %3Cpolygon points%3D%2278.42 43.9 84 44.45 84 33.22 78.42 31.55 78.42 43.9%22 fill%3D%22%23f58536%22%2F%3E %3Cpolygon points%3D%2271.62 43.22 63.13 42.37 63.13 26.96 71.62 29.51 71.62 43.22%22 fill%3D%22%23f58536%22%2F%3E %3Cpolygon points%3D%2278.42 56.33 84 55.77 84 67 78.42 68.67 78.42 56.33%22 fill%3D%22%23f58536%22%2F%3E %3Cpolygon points%3D%2271.62 57.01 63.13 57.86 63.13 73.26 71.62 70.72 71.62 57.01%22 fill%3D%22%23f58536%22%2F%3E %3C%2Fg%3E%3C%2Fsvg%3E");\n}\n');const At="spinnaker.ecs";t(At,[Qe,bt,De,ft,et,it,mt,rt,ct,pt,nt,ot,Ee,Ve,Me,He,ke,st,Xe,Ge,Le,Re,$e,Be,Fe,Oe,Ue,qe,Ze,Gt,xe]).config((function(){i.registerProvider("ecs",{name:"EC2 Container Service",logo:{path:"data:image/svg+xml,%3Csvg%20id%3D%22Layer_1%22%20data-name%3D%22Layer%201%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22100%22%20height%3D%22100%22%20viewBox%3D%220%200%20100%20100%22%3E%20%20%3Ctitle%3ECompute%3C%2Ftitle%3E%20%20%3Cg%3E%20%20%20%20%3Cpolygon%20points%3D%2219.64%2022.51%2016%2024.32%2016%2075.68%2019.64%2077.49%2033.98%2051.07%2019.64%2022.51%22%20fill%3D%22%239d5025%22%2F%3E%20%20%20%20%3Cpolygon%20points%3D%2230.72%2031.78%2036.08%2024.19%2060.1%2034.87%2054.5%2035.76%2030.72%2031.78%22%20fill%3D%22%239d5025%22%2F%3E%20%20%20%20%3Cpolygon%20points%3D%2226.56%2068.77%2032.46%2076.88%2060.1%2064.95%2054.76%2064.12%2026.56%2068.77%22%20fill%3D%22%239d5025%22%2F%3E%20%20%20%20%3Cpolygon%20points%3D%2228.12%2075.5%2019.64%2077.49%2019.64%2022.51%2028.12%2024.44%2028.12%2075.5%22%20fill%3D%22%23f58536%22%2F%3E%20%20%20%20%3Cpolygon%20points%3D%2223.66%2020.5%2028.12%2018.27%2036.52%2053.56%2028.12%2081.73%2023.66%2079.5%2023.66%2020.5%22%20fill%3D%22%239d5025%22%2F%3E%20%20%20%20%3Cpolygon%20points%3D%2254.46%2064.08%2060.1%2064.95%2065.26%2050.58%2060.1%2034.87%2054.46%2035.76%2054.46%2064.08%22%20fill%3D%22%239d5025%22%2F%3E%20%20%20%20%3Cpolygon%20points%3D%2236.8%2079.28%2028.12%2081.73%2028.12%2018.27%2036.8%2020.73%2036.8%2079.28%22%20fill%3D%22%23f58536%22%2F%3E%20%20%20%20%3Cpolygon%20points%3D%2266.01%2063.84%2028.12%2070.88%2028.12%2081.73%2066.01%2071.03%2066.01%2063.84%22%20fill%3D%22%23f58536%22%2F%3E%20%20%20%20%3Cpolygon%20points%3D%2266.08%2036%2028.12%2028.79%2028.12%2018.27%2066.08%2029.04%2066.08%2036%22%20fill%3D%22%23f58536%22%2F%3E%20%20%20%20%3Cpolygon%20points%3D%2260.1%2027.34%2066.19%2029.02%2066.19%2071.03%2060.1%2072.7%2060.1%2027.34%22%20fill%3D%22%23f58536%22%2F%3E%20%20%20%20%3Cpolygon%20points%3D%2284%2044.45%2067.7%2045.22%2061.94%2044.83%2078.42%2031.55%2084%2044.45%22%20fill%3D%22%236b3a19%22%2F%3E%20%20%20%20%3Cpolygon%20points%3D%2261.94%2044.83%2078.42%2043.9%2078.42%2031.55%2061.94%2034.22%2061.94%2044.83%22%20fill%3D%22%239d5025%22%2F%3E%20%20%20%20%3Cpolygon%20points%3D%2246.43%2043.79%2063.13%2026.96%2071.62%2043.22%2054.31%2044.32%2046.43%2043.79%22%20fill%3D%22%236b3a19%22%2F%3E%20%20%20%20%3Cpolygon%20points%3D%2246.43%2043.79%2063.13%2042.37%2063.13%2026.96%2046.43%2030.87%2046.43%2043.79%22%20fill%3D%22%239d5025%22%2F%3E%20%20%20%20%3Cpolygon%20points%3D%2261.94%2055.39%2084%2055.77%2078.42%2068.67%2061.94%2066%2061.94%2055.39%22%20fill%3D%22%239d5025%22%2F%3E%20%20%20%20%3Cpolygon%20points%3D%2246.43%2056.43%2071.62%2057.01%2063.13%2073.26%2046.43%2069.36%2046.43%2056.43%22%20fill%3D%22%239d5025%22%2F%3E%20%20%20%20%3Cpolygon%20points%3D%2246.43%2056.43%2063.13%2057.86%2071.62%2057.01%2054.31%2055.9%2046.43%2056.43%22%20fill%3D%22%23fbbf93%22%2F%3E%20%20%20%20%3Cpolygon%20points%3D%2284%2055.77%2067.7%2055.01%2061.94%2055.39%2078.42%2056.33%2084%2055.77%22%20fill%3D%22%23fbbf93%22%2F%3E%20%20%20%20%3Cpolygon%20points%3D%2278.42%2043.9%2084%2044.45%2084%2033.22%2078.42%2031.55%2078.42%2043.9%22%20fill%3D%22%23f58536%22%2F%3E%20%20%20%20%3Cpolygon%20points%3D%2271.62%2043.22%2063.13%2042.37%2063.13%2026.96%2071.62%2029.51%2071.62%2043.22%22%20fill%3D%22%23f58536%22%2F%3E%20%20%20%20%3Cpolygon%20points%3D%2278.42%2056.33%2084%2055.77%2084%2067%2078.42%2068.67%2078.42%2056.33%22%20fill%3D%22%23f58536%22%2F%3E%20%20%20%20%3Cpolygon%20points%3D%2271.62%2057.01%2063.13%2057.86%2063.13%2073.26%2071.62%2070.72%2071.62%2057.01%22%20fill%3D%22%23f58536%22%2F%3E%20%20%3C%2Fg%3E%3C%2Fsvg%3E"},serverGroup:{transformer:"ecsServerGroupTransformer",detailsTemplateUrl:"ecs/src/serverGroup/details/serverGroupDetails.html",detailsController:"ecsServerGroupDetailsCtrl",cloneServerGroupTemplateUrl:"ecs/src/serverGroup/configure/wizard/serverGroupWizard.html",cloneServerGroupController:"ecsCloneServerGroupCtrl",commandBuilder:"ecsServerGroupCommandBuilder",scalingActivitiesEnabled:!1,skipUpstreamStageCheck:!0},loadBalancer:{transformer:ze,ClusterContainer:Te,targetGroupDetails:Ie,details:Pe},instance:{detailsTemplateUrl:"ecs/src/instance/details/instanceDetails.html",detailsController:"ecsInstanceDetailsCtrl"},securityGroup:{transformer:"ecsSecurityGroupTransformer",reader:"ecsSecurityGroupReader",detailsTemplateUrl:"ecs/src/securityGroup/details/securityGroupDetail.html",detailsController:"ecsSecurityGroupDetailsCtrl"}})})),H.registerProvider("ecs",["redblack"]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/serverGroup/details/serverGroupDetails.html",'<div class="details-panel" ng-class="{ disabled: ctrl.serverGroup.isDisabled }">\n <div class="header" ng-if="ctrl.state.loading">\n <div class="close-button">\n <a class="btn btn-link" ui-sref="^">\n <span class="glyphicon glyphicon-remove"></span>\n </a>\n </div>\n <h4 class="text-center">\n <span us-spinner="{radius:20, width:6, length: 12}"></span>\n </h4>\n </div>\n\n <div class="header" ng-if="!ctrl.state.loading">\n <div class="close-button">\n <a class="btn btn-link" ui-sref="^">\n <span class="glyphicon glyphicon-remove"></span>\n </a>\n </div>\n <div class="header-text horizontal middle">\n <cloud-provider-logo provider="ctrl.serverGroup.type" height="\'36px\'" width="\'36px\'"></cloud-provider-logo>\n <h3 class="horizontal middle space-between flex-1" select-on-dbl-click>\n {{ctrl.serverGroup.name}}\n <render-if-feature feature="entityTags">\n <entity-notifications\n entity="ctrl.serverGroup"\n application="ctrl.application"\n placement="bottom"\n h-offset-percent="90%"\n entity-type="serverGroup"\n page-location="details"\n on-update="ctrl.application.serverGroups.refresh()"\n ></entity-notifications>\n </render-if-feature>\n </h3>\n </div>\n <div>\n <div class="actions" ng-class="{ insights: ctrl.serverGroup.insightActions.length > 0 }">\n <div class="dropdown" uib-dropdown dropdown-append-to-body>\n <button type="button" class="btn btn-sm btn-primary dropdown-toggle" uib-dropdown-toggle>\n Server Group Actions <span class="caret"></span>\n </button>\n <ul class="dropdown-menu" uib-dropdown-menu role="menu">\n <li><a href ng-if=" !ctrl.serverGroup.isDisabled" ng-click="ctrl.rollbackServerGroup()">Rollback</a></li>\n <li role="presentation" class="divider" ng-if=" !ctrl.serverGroup.isDisabled"></li>\n <li><a href ng-click="ctrl.resizeServerGroup()">Resize</a></li>\n <li><a href ng-if=" !ctrl.serverGroup.isDisabled" ng-click="ctrl.disableServerGroup()">Disable</a></li>\n <li>\n <a href ng-if="ctrl.serverGroup.isDisabled && !ctrl.isEnableLocked()" ng-click="ctrl.enableServerGroup()"\n >Enable</a\n >\n </li>\n <li class="disabled" ng-if="ctrl.isEnableLocked()">\n <a\n uib-tooltip="Cannot enable this server group until resize operation completes"\n tooltip-placement="left"\n >\n <span class="small glyphicon glyphicon-lock"></span>\n Enable\n </a>\n </li>\n <li><a href ng-click="ctrl.destroyServerGroup()">Destroy</a></li>\n <li><migrator application="ctrl.application" server-group="ctrl.serverGroup"></migrator></li>\n <render-if-feature feature="entityTags">\n <add-entity-tag-links\n component="ctrl.serverGroup"\n application="ctrl.application"\n entity-type="serverGroup"\n owner-options="ctrl.entityTagTargets"\n on-update="ctrl.application.serverGroups.refresh"\n ></add-entity-tag-links>\n </render-if-feature>\n </ul>\n </div>\n <div class="dropdown" ng-if="ctrl.serverGroup.insightActions.length > 0" uib-dropdown dropdown-append-to-body>\n <button type="button" class="btn btn-sm btn-default dropdown-toggle" uib-dropdown-toggle>\n Insight <span class="caret"></span>\n </button>\n <ul class="dropdown-menu" uib-dropdown-menu role="menu">\n <li ng-repeat="action in ctrl.serverGroup.insightActions">\n <a target="_blank" href="{{action.url}}">{{action.label}}</a>\n </li>\n </ul>\n </div>\n </div>\n </div>\n </div>\n <div class="band band-info" ng-if="ctrl.serverGroup.isDisabled">Disabled {{ctrl.disabledDate | timestamp}}</div>\n <div class="content" ng-if="!ctrl.state.loading">\n <server-group-running-tasks-details\n server-group="ctrl.serverGroup"\n application="ctrl.application"\n ></server-group-running-tasks-details>\n <collapsible-section heading="General" expanded="true">\n <dl class="dl-horizontal dl-narrow">\n <dt>Created</dt>\n <dd>{{ctrl.serverGroup.createdTime | timestamp}}</dd>\n <render-if-feature feature="entityTags">\n <entity-source metadata="ctrl.serverGroup.entityTags.creationMetadata"></entity-source>\n <view-changes-link\n change-config="ctrl.changeConfig"\n jar-diffs="ctrl.jarDiffs"\n link-text="view changes"\n name-item="ctrl.serverGroup"\n ></view-changes-link>\n </render-if-feature>\n <dt>In</dt>\n <dd>\n <account-tag account="ctrl.serverGroup.account" pad="right"></account-tag>\n <br />\n {{ctrl.serverGroup.region}}\n </dd>\n <dt>ECS Cluster</dt>\n <dd>{{ctrl.serverGroup.ecsCluster}}</dd>\n <dt>VPC ID</dt>\n <dd>{{ctrl.serverGroup.vpcId}}</dd>\n </dl>\n </collapsible-section>\n <collapsible-section heading="Definitions" expanded="true">\n <dl class="horizontal-when-filters-collapsed">\n <dt>Task Name</dt>\n <dd>{{ctrl.serverGroup.taskDefinition.taskName}}</dd>\n\n <dt>Container URL</dt>\n <dd>{{ctrl.serverGroup.taskDefinition.containerImage}}</dd>\n\n <dt>Container IAM Profile</dt>\n <dd>{{ctrl.serverGroup.taskDefinition.iamRole}}</dd>\n\n <dt ng-if="ctrl.serverGroup.taskDefinition.containerPort">Container Port</dt>\n <dd ng-if="ctrl.serverGroup.taskDefinition.containerPort">{{ctrl.serverGroup.taskDefinition.containerPort}}</dd>\n\n <dt>Container CPU Units</dt>\n <dd>{{ctrl.serverGroup.taskDefinition.cpuUnits}}</dd>\n\n <dt ng-if="ctrl.serverGroup.taskDefinition.memoryReservation">Container Reserved Memory</dt>\n <dd ng-if="ctrl.serverGroup.taskDefinition.memoryReservation">\n {{ctrl.serverGroup.taskDefinition.memoryReservation}} mb\n </dd>\n\n <dt ng-if="ctrl.serverGroup.taskDefinition.memoryLimit">Container Memory Limit</dt>\n <dd ng-if="ctrl.serverGroup.taskDefinition.memoryLimit">{{ctrl.serverGroup.taskDefinition.memoryLimit}} mb</dd>\n </dl>\n </collapsible-section>\n <collapsible-section heading="Environment Variables" expanded="false">\n <div ng-if="!ctrl.serverGroup.taskDefinition.environmentVariables.length">\n This server group has no environment variables\n </div>\n <dl ng-if="ctrl.serverGroup.taskDefinition.environmentVariables.length">\n <dt ng-repeat-start="variable in ctrl.serverGroup.taskDefinition.environmentVariables">{{variable.name}}</dt>\n <dd ng-repeat-end>{{variable.value}}</dd>\n </dl>\n </collapsible-section>\n <collapsible-section heading="Health" expanded="true" ng-if="ctrl.serverGroup.instanceCounts.total > 0">\n <dl class="dl-horizontal dl-narrow" ng-if="ctrl.serverGroup">\n <dt>Instances</dt>\n <dd>\n <health-counts container="ctrl.serverGroup.instanceCounts" class="pull-left"></health-counts>\n </dd>\n </dl>\n </collapsible-section>\n <collapsible-section heading="{{ctrl.firewallsLabel}}" expanded="false">\n <ul>\n <li ng-repeat="securityGroup in ctrl.serverGroup.securityGroups">{{securityGroup}}</li>\n </ul>\n </collapsible-section>\n <collapsible-section heading="Capacity" expanded="false">\n <dl class="dl-horizontal dl-narrow">\n <dt>Current</dt>\n <dd>{{ctrl.serverGroup.instances.length}}</dd>\n\n <dt>Desired</dt>\n <dd>{{ctrl.serverGroup.capacity.desired}}</dd>\n\n <dt>Min</dt>\n <dd>{{ctrl.serverGroup.capacity.min}}</dd>\n\n <dt>Max</dt>\n <dd>{{ctrl.serverGroup.capacity.max}}</dd>\n </dl>\n </collapsible-section>\n <collapsible-section heading="Scaling Policies" expanded="false">\n <dl class="horizontal-when-filters-collapsed">\n <dd\n ng-if="ctrl.serverGroup.metricAlarms.length > 0"\n ng-repeat="metricAlarmName in ctrl.serverGroup.metricAlarms"\n >\n {{metricAlarmName}}\n </dd>\n <dd ng-if="ctrl.serverGroup.metricAlarms.length <= 0"><i>There are no scaling policies assigned.</i></dd>\n </dl>\n </collapsible-section>\n <collapsible-section heading="Build data" ng-if="ctrl.serverGroup.buildInfo && ctrl.serverGroup.buildInfo.jenkins">\n <dl class="horizontal-when-filters-collapsed">\n <dt>Job</dt>\n <dd>{{ctrl.serverGroup.buildInfo.jenkins.name}}</dd>\n <dt>Package</dt>\n <dd>{{ctrl.serverGroup.buildInfo.package_name}}</dd>\n <dt>Build</dt>\n <dd>{{ctrl.serverGroup.buildInfo.jenkins.number}}</dd>\n <dt>Commit</dt>\n <dd>{{ctrl.truncateCommitHash()}}</dd>\n <dt>Version</dt>\n <dd>{{ctrl.serverGroup.buildInfo.version}}</dd>\n <dt>Build Link</dt>\n <dd><a target="_blank" href="{{ctrl.buildJenkinsLink()}}">{{ctrl.buildJenkinsLink()}}</a></dd>\n </dl>\n </collapsible-section>\n <collapsible-section heading="Server Group Logs">\n <ul>\n <li>\n <view-events-link server-group="ctrl.serverGroup"></view-events-link>\n </li>\n </ul>\n </collapsible-section>\n </div>\n</div>\n')}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/serverGroup/configure/wizard/serverGroupWizard.html",'<form name="form" class="form-horizontal" novalidate>\n <div ng-if="state.requiresTemplateSelection">\n <ng-include src="pages.templateSelection"></ng-include>\n </div>\n <div ng-if="!state.loaded" style="height: 200px">\n <h3 us-spinner="{radius:30, width:8, length: 16}"></h3>\n </div>\n <div ng-if="!state.requiresTemplateSelection">\n <v2-modal-wizard ng-show="state.loaded" heading="{{title}}" task-monitor="taskMonitor" dismiss="$dismiss()">\n <v2-wizard-page key="basicSettings" label="Basic Settings" mark-complete-on-view="false" done="true">\n <ng-include src="pages.basicSettings"></ng-include>\n </v2-wizard-page>\n <v2-wizard-page key="networking" label="Networking" done="true">\n <ng-include src="pages.networking"></ng-include>\n </v2-wizard-page>\n <v2-wizard-page key="taskDefinition" label="Task Definition" done="true">\n <ng-include src="pages.taskDefinition"></ng-include>\n </v2-wizard-page>\n <div ng-if="!command.useTaskDefinitionArtifact">\n <v2-wizard-page key="container" label="Container" done="true">\n <ng-include src="pages.container"></ng-include>\n </v2-wizard-page>\n </div>\n <v2-wizard-page key="horizontalScaling" label="Horizontal Scaling" done="true">\n <ng-include src="pages.horizontalScaling"></ng-include>\n </v2-wizard-page>\n <div ng-if="!command.useTaskDefinitionArtifact">\n <v2-wizard-page key="logging" label="Logging" done="true">\n <ng-include src="pages.logging"></ng-include>\n </v2-wizard-page>\n </div>\n <v2-wizard-page key="serviceDiscovery" label="Service Discovery" done="true">\n <ng-include ng-if="!command.useTaskDefinitionArtifact" src="pages.serviceDiscovery"></ng-include>\n <ng-include ng-if="command.useTaskDefinitionArtifact" src="pages.serviceDiscovery"></ng-include>\n </v2-wizard-page>\n <v2-wizard-page key="advanced" label="Advanced Settings" mark-complete-on-view="false" done="true">\n <ng-include src="pages.advancedSettings"></ng-include>\n </v2-wizard-page>\n </v2-modal-wizard>\n <div class="modal-footer" ng-if="state.loaded">\n <button ng-disabled="taskMonitor.submitting" class="btn btn-default btn-cancel" ng-click="ctrl.cancel()">\n Cancel\n </button>\n <submit-button\n data-test-id="ServerGroupWizard.submitButton"\n ng-if="ctrl.showSubmitButton()"\n is-disabled="!ctrl.isValid() || taskMonitor.submitting"\n label="command.viewState.submitButtonLabel"\n submitting="taskMonitor.submitting"\n on-click="ctrl.submit()"\n is-new="true"\n ></submit-button>\n </div>\n </div>\n</form>\n')}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/instance/details/instanceDetails.html",'<div class="text-center" ng-if="state.notFoundStandalone">\n <h3>Could not find instance {{instanceIdNotFound}}.</h3>\n <a ui-sref="home.infrastructure">Back to search results</a>\n</div>\n<div class="details-panel" ng-if="!state.notFoundStandalone">\n <div class="header">\n <instance-details-header\n health-state="instance.healthState"\n instance-id="instance ? instance.name : instanceIdNotFound"\n loading="state.loading"\n standalone="state.standalone"\n ></instance-details-header>\n <div ng-if="!state.loading">\n <div class="actions" ng-class="{ insights: instance.insightActions.length > 0 }">\n \x3c!-- TODO - find out what I should do with ng-if="instance.placement" --\x3e\n <div class="dropdown" uib-dropdown dropdown-append-to-body>\n <button\n type="button"\n class="btn btn-sm btn-primary dropdown-toggle"\n ng-disabled="disabled"\n uib-dropdown-toggle\n >\n Instance Actions <span class="caret"></span>\n </button>\n <ul class="dropdown-menu" uib-dropdown-menu role="menu">\n <li>\n <a href ng-click="ctrl.enableInstanceInDiscovery()" ng-if="ctrl.canRegisterWithDiscovery()"\n >Enable in Discovery</a\n >\n </li>\n <li>\n <a\n href\n ng-click="ctrl.disableInstanceInDiscovery()"\n ng-if="ctrl.hasHealthState(\'Discovery\', \'Up\') || ctrl.hasHealthState(\'Discovery\', \'Down\')"\n >Disable in Discovery</a\n >\n </li>\n <li>\n <a href ng-click="ctrl.registerInstanceWithLoadBalancer()" ng-if="ctrl.canRegisterWithLoadBalancer()"\n >Register with Load Balancer</a\n >\n </li>\n <li>\n <a href ng-click="ctrl.deregisterInstanceFromLoadBalancer()" ng-if="ctrl.canDeregisterFromLoadBalancer()"\n >Deregister from Load Balancer</a\n >\n </li>\n <li>\n <a href ng-click="ctrl.registerInstanceWithTargetGroup()" ng-if="ctrl.canRegisterWithTargetGroup()"\n >Register with Target Group</a\n >\n </li>\n <li>\n <a href ng-click="ctrl.deregisterInstanceFromTargetGroup()" ng-if="ctrl.canDeregisterFromTargetGroup()"\n >Deregister from Target Group</a\n >\n </li>\n \x3c!--<li role="presentation" class="divider" ng-if="instance.health.length > 0"></li>--\x3e\n </ul>\n </div>\n <div class="dropdown" ng-if="instance.insightActions.length > 0" uib-dropdown dropdown-append-to-body>\n <button type="button" class="btn btn-sm btn-default dropdown-toggle" uib-dropdown-toggle>\n Insight <span class="caret"></span>\n </button>\n <ul class="dropdown-menu" uib-dropdown-menu role="menu">\n <li ng-repeat="action in instance.insightActions">\n <a target="_blank" href="{{action.url}}">{{action.label}}</a>\n </li>\n </ul>\n </div>\n </div>\n </div>\n </div>\n <div class="content" data-test-id="instanceDetails.content" ng-if="!state.loading && instance">\n <collapsible-section heading="Instance Information" expanded="true">\n <dl class="dl-horizontal dl-narrow">\n <dt>Launched</dt>\n <dd ng-if="instance.launchTime">{{instance.launchTime | timestamp}}</dd>\n <dd ng-if="!instance.launchTime">(Unknown)</dd>\n <dt ng-if="instance.serverGroup">Server Group</dt>\n <dd ng-if="instance.serverGroup">\n <a\n ui-sref="^.serverGroup({region: instance.region,\n accountId: instance.account,\n serverGroup: instance.serverGroup,\n provider: instance.provider})"\n >{{instance.serverGroup}}</a\n >\n </dd>\n <dt ng-if="instance.imageId">Image ID</dt>\n <dd ng-if="instance.imageId">{{instance.imageId}}</dd>\n </dl>\n </collapsible-section>\n <collapsible-section heading="Status" expanded="true">\n <p ng-if="instance.healthState !== \'Starting\' && !healthMetrics.length">\n No health metrics found for this instance\n </p>\n <p ng-if="instance.healthState === \'Starting\' && !healthMetrics.length">\n <span class="glyphicon glyphicon-Starting-triangle"></span> <strong>Starting</strong>\n </p>\n\n <dl class="horizontal-when-filters-collapsed">\n <dt ng-repeat-start="metric in healthMetrics | orderBy: \'type\'">{{metric.type | robotToHuman}}</dt>\n <dd ng-repeat-end>\n <div ng-if="metric.type !== \'LoadBalancer\' && metric.type !== \'TargetGroup\'">\n <span\n uib-tooltip="{{metric.state.toLowerCase() === \'down\' ? metric.description : \'\'}}"\n tooltip-placement="left"\n >\n <span class="glyphicon glyphicon-{{metric.state}}-triangle"></span>\n {{metric.state | robotToHuman}}\n </span>\n <span class="pad-left small">\n <a ng-if="metric.healthCheckUrl" target="_blank" href="{{metric.healthCheckUrl}}">Health Check</a>\n <span ng-if="metric.healthCheckUrl && metric.statusPageUrl"> | </span>\n <a ng-if="metric.statusPageUrl" target="_blank" href="{{metric.statusPageUrl}}">Status</a>\n </span>\n </div>\n <div\n ng-if="metric.type === \'LoadBalancer\' && metric.loadBalancers.length"\n ng-repeat="loadBalancer in metric.loadBalancers"\n >\n <instance-load-balancer-health load-balancer="loadBalancer"></instance-load-balancer-health>\n </div>\n <div\n ng-if="metric.type === \'TargetGroup\' && metric.targetGroups.length"\n ng-repeat="targetGroup in metric.targetGroups"\n >\n <instance-load-balancer-health\n load-balancer="targetGroup"\n ip-address="baseIpAddress"\n ></instance-load-balancer-health>\n </div>\n </dd>\n </dl>\n </collapsible-section>\n <collapsible-section heading="Networking">\n <dl class="horizontal-when-filters-collapsed">\n <dt ng-if="instance.vpcId">VPC</dt>\n <dd ng-if="instance.vpcId"><vpc-tag vpc-id="instance.vpcId"></vpc-tag></dd>\n <dt ng-if="instance.subnetId">Subnet</dt>\n <dd ng-if="instance.subnetId"><subnet-tag subnet-id="instance.subnetId"></subnet-tag></dd>\n\n <dt ng-if="instance.privateAddress || instance.networkInterface">IP</dt>\n <dd ng-if="instance.networkInterface.privateIpv4Address">\n Private address (ENI):\n <a href="http://{{instance.networkInterface.privateIpv4Address}}" target="_blank"\n >{{instance.networkInterface.privateIpv4Address}}</a\n >\n <copy-to-clipboard\n class="copy-to-clipboard copy-to-clipboard-sm"\n text="instance.networkInterface.privateIpv4Address"\n tool-tip="\'Copy to clipboard\'"\n >\n </copy-to-clipboard>\n </dd>\n <dd ng-if="instance.networkInterface.ipv6Address">\n Private address (ENI):\n <a href="http://{{instance.networkInterface.ipv6Address}}" target="_blank"\n >{{instance.networkInterface.ipv6Address}}</a\n >\n <copy-to-clipboard\n class="copy-to-clipboard copy-to-clipboard-sm"\n text="instance.networkInterface.ipv6Address"\n tool-tip="\'Copy to clipboard\'"\n >\n </copy-to-clipboard>\n </dd>\n <dd ng-if="instance.privateAddress">\n Private address (Bridge):\n <a href="http://{{instance.privateAddress}}" target="_blank">{{instance.privateAddress}}</a>\n <copy-to-clipboard\n class="copy-to-clipboard copy-to-clipboard-sm"\n text="instance.privateAddress"\n tool-tip="\'Copy to clipboard\'"\n >\n </copy-to-clipboard>\n </dd>\n </dl>\n </collapsible-section>\n <collapsible-section heading="Console Output" ng-if="baseIpAddress">\n <ul>\n <li>\n <console-output-link instance="instance"></console-output-link>\n </li>\n </ul>\n </collapsible-section>\n <instance-links\n address="baseIpAddress"\n application="application"\n instance="instance"\n moniker="moniker"\n environment="environment"\n ></instance-links>\n </div>\n <div class="content" ng-if="!state.loading && !instance">\n <div class="content-section">\n <div class="content-body text-center">\n <h3>Instance not found.</h3>\n </div>\n </div>\n </div>\n</div>\n')}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/securityGroup/details/securityGroupDetail.html",'<div class="text-center" ng-if="state.notFound">\n <h3>Could not find <firewall-label label="firewall"></firewall-label> {{group}}.</h3>\n <a ui-sref="home.infrastructure">Back to search results</a>\n</div>\n<div class="details-panel" ng-if="!state.notFound">\n <div class="header">\n <div class="close-button" ng-if="!state.standalone">\n <a class="btn btn-link" ui-sref="^">\n <span class="glyphicon glyphicon-remove"></span>\n </a>\n </div>\n <div ng-if="state.loading" class="horizontal center middle">\n <loading-spinner size="\'small\'"></loading-spinner>\n </div>\n <div class="header-text horizontal middle" ng-if="!state.loading">\n <span class="glyphicon glyphicon-transfer"></span>\n <h3 class="horizontal middle space-between flex-1" select-on-dbl-click>\n {{securityGroup.name || \'(not found)\'}}\n <render-if-feature feature="entityTags">\n <entity-notifications\n entity="securityGroup"\n application="ctrl.application"\n placement="bottom"\n h-offset-percent="90%"\n entity-type="securityGroup"\n page-location="details"\n on-update="ctrl.application.securityGroups.refresh()"\n ></entity-notifications>\n </render-if-feature>\n </h3>\n </div>\n </div>\n <div class="content" ng-if="!state.loading">\n <collapsible-section heading="{{ctrl.firewallLabel}} Details" expanded="true">\n <dl class="dl-horizontal dl-medium">\n <dt>ID</dt>\n <dd>{{securityGroup.id}}</dd>\n <dt>Account</dt>\n <dd>\n <account-tag account="securityGroup.accountName"></account-tag>\n </dd>\n <dt>Region</dt>\n <dd>{{securityGroup.region}}</dd>\n <dt>VPC</dt>\n <dd>\n <vpc-tag vpc-id="securityGroup.vpcId"></vpc-tag>\n </dd>\n <dt>Description</dt>\n <dd>{{securityGroup.description}}</dd>\n </dl>\n </collapsible-section>\n <collapsible-section heading="IP Range Rules ({{ipRules.length}})" expanded="{{ipRules.length > 0}}">\n <div ng-if="!ipRules.length">None</div>\n\n <dl\n ng-class="insightCtrl.vm.filtersExpanded ? \'\' : \'dl-horizontal dl-medium\'"\n ng-repeat="ipRangeRule in ipRules | orderBy: \'range.address\'"\n >\n <dt>IP Range</dt>\n <dd>{{ipRangeRule.address}}</dd>\n <dt>Port Ranges</dt>\n <dd ng-repeat="rule in ipRangeRule.rules">\n <span ng-if="rule.protocol === \'-1\'">\n All ports and protocols\n <div ng-if="ipRangeRule.rules.length > 1">\n <em>Additional port ranges are specified, but redundant:</em>\n </div>\n </span>\n <span ng-if="rule.protocol !== \'-1\'"> {{rule.protocol}}: {{rule.startPort}} → {{rule.endPort}} </span>\n </dd>\n </dl>\n </collapsible-section>\n <collapsible-section\n heading="{{ctrl.firewallLabel}} Rules ({{securityGroupRules.length || 0}})"\n expanded="{{securityGroupRules.length > 0}}"\n >\n <div ng-if="!securityGroupRules.length">None</div>\n\n <dl\n ng-class="insightCtrl.vm.filtersExpanded ? \'\' : \'dl-horizontal dl-medium\'"\n ng-repeat="rule in securityGroupRules | orderBy: \'securityGroup.name\' "\n >\n <dt>\n <firewall-label label="Firewall"></firewall-label>\n </dt>\n <dd ng-if="rule.securityGroup.name">\n <a\n ui-sref="^.firewallDetails({name: rule.securityGroup.name, accountId: rule.securityGroup.accountName, region: rule.securityGroup.region, vpcId: rule.securityGroup.vpcId, provider: \'ecs\'})"\n >\n <account-tag\n account="rule.securityGroup.accountName || rule.securityGroup.accountId"\n ng-if="rule.securityGroup.accountName !== securityGroup.accountName"\n ></account-tag>\n {{rule.securityGroup.name}} ({{rule.securityGroup.id}})\n </a>\n </dd>\n <dt>Port Ranges</dt>\n <dd ng-repeat="portRange in rule.rules">\n {{portRange.protocol}}: {{portRange.startPort}} → {{portRange.endPort}}\n </dd>\n </dl>\n </collapsible-section>\n </div>\n</div>\n')}]);export{At as ECS_MODULE};
|
|
1
|
+
import*as e from"angular";import{module as t}from"angular";import{HelpContentsRegistry as n,SETTINGS as a,REST as r,CloudProviderRegistry as i,ConfirmationModalService as s,InstanceWriter as o,RecentHistoryService as l,InstanceReader as c,LoadBalancerServerGroup as d,Spinner as p,CollapsibleSection as u,timestamp as m,AccountTag as g,APPLICATION_STATE_PROVIDER as v,Registry as h,AccountService as f,StageConstants as y,PipelineTemplates as b,SECURITY_GROUP_READER as S,MANAGED_RESOURCE_DETAILS_INDICATOR as k,FirewallLabels as C,LOAD_BALANCER_READ_SERVICE as w,CACHE_INITIALIZER_SERVICE as E,SERVER_GROUP_COMMAND_REGISTRY_PROVIDER as D,SubnetReader as G,NameUtils as A,INSTANCE_TYPE_SERVICE as T,SERVER_GROUP_WRITER as N,OVERRIDE_REGISTRY as P,STAGE_ARTIFACT_SELECTOR_COMPONENT_REACT as I,TaskMonitor as z,ModalWizard as x,TetheredSelect as M,HelpField as R,withErrorBoundary as $,ArtifactTypePatterns as B,StageArtifactSelectorDelegate as F,StageConfigField as L,CheckboxInput as O,ServerGroupWarningMessageService as U,ServerGroupReader as q,DeploymentStrategyRegistry as H}from"@spinnaker/core";import V from"@uirouter/angularjs";import _ from"angular-ui-bootstrap";import j,{isEqual as W,clone as Z,has as K,flatten as J,keys as Y,chain as X,find as Q,intersection as ee,xor as te,extend as ne,some as ae,uniqWith as re,defaults as ie,filter as se,isEmpty as oe}from"lodash";import{getAllTargetGroups as le,applyHealthCheckInfoToTargetGroups as ce,VpcReader as de}from"@spinnaker/amazon";import*as pe from"react";import ue from"react";import{UISrefActive as me,UISref as ge}from"@uirouter/react";import{DockerImageReader as ve}from"@spinnaker/docker";import{Alert as he}from"react-bootstrap";import{react2angular as fe}from"react2angular";import{$log as ye}from"ngimport";const be={bindings:{action:"&",isValid:"&",cancel:"&",account:"=?",verification:"=?"},template:'\n <div class="modal-footer">\n <user-verification account="$ctrl.account" verification="$ctrl.verification"></user-verification>\n <button type="submit" ng-click="$ctrl.action()" style="display:none"></button> \x3c!-- Allows form submission via enter keypress--\x3e\n <button class="btn btn-default" ng-click="$ctrl.cancel()">Cancel</button>\n <button type="submit"\n class="btn btn-primary"\n ng-click="$ctrl.action()"\n ng-disabled="!$ctrl.isValid()">\n Submit\n </button>\n </div>\n ',controller:()=>{}},Se="spinnaker.ecs.footer";t(Se,[]).component("ecsFooter",be);const ke="spinnaker.ecs.common";t(ke,[Se]);const Ce={"ecs.loadBalancer.targetGroup":"<p>A <em>target group</em> is attached to an application / network load balancer and is a target for load balancer traffic.</p> <p> You need to create both the application load balancer and target groups prior to being able to use them in your pipeline.</p>","ecs.serverGroup.clusterName":"<p>The name of the ECS cluster (group of underlying EC2 hosts) onto which your application will be deployed.</p><p>Note that suggestions here are dependent on the selected account and region combination.</p>","ecs.stage.findImageByTags.labelOrSha":"<p>As of now, only Amazon's ECR is supported as a source docker repository.</p>","ecs.serverGroup.stack":"<p>An environment variable available within your container, and on which you should base your application configuration at runtime.</p> <p>Typical values for this parameter are <i>staging</i>, <i>prod</i>, etc. Keep this parameter short!</p>","ecs.serverGroup.detail":"<p>An environment variable available within your container, and on which you should base your application configuration at runtime.</p> <p>Typical values for this parameter are <i>app</i>, <i>worker</i>, <i>migrator</i>, etc. Keep this parameter short!</p>","ecs.capacity.overwrite":"<p>Checking this box will have the previous server group's capacity overwrite the new <i>min</i>, <i>max</i> and <i>desired capacity</i> parameters if a previous server group exists.</p>","ecs.capacity.desired":"<p>The starting number of containers, before any autoscaling happens.</p>","ecs.capacity.minimum":"<p>The minimum number of containers you can reach as a result of autoscaling.</p> <p>Typically, this represents the bare minimum you can afford to run without impacting your capacity to meet your SLA (Service Level Agreement) objectives</p>","ecs.capacity.maximum":"<p>The maximal number of containers you can reach as a result of autoscaling.</p>","ecs.capacity.reserved.computeUnits":"<p>The assured minimal amount of computing capacity your container will be able to use. 1024 units are equal to 1 AWS virtual CPU</p> <p>If other containers on your underlying host are not using their reserved compute capacity, this container will be able to use it.</p>","ecs.capacity.reserved.memory":"<p>The maximal amount of memory that your container can use, in megabytes. Exceeding this amount may result in termination of your container.</p><p>1024 mb = 1 gb</p>","ecs.loadbalancing.targetPort":"<p>The port on which your application is listening for incoming traffic</p>","ecs.iamrole":"<p>The IAM role that your container (task, in AWS wording) will inherit. </p><p>Define a role only if your application needs to access AWS APIs</p>","ecs.dockerimage":"Docker image for your container, such as nginx:latest","ecs.dockerimagecredentials":"<p>The AWS Secrets Manager secret that contains private registry credentials.</p><p>Define credentials only for private registries other than Amazon ECR.</p>","ecs.placementConstraints":'<p>Rules for task placement. See <a href="https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-placement-constraints.html" target="_blank">AWS documentation</a> for more details. </p>',"ecs.placementConstraintType":"<p>To ensure that each task in a particular group is running on a different container instance, use distinctInstance. To restrict the selection to a group of valid candidates, use memberOf. </p>","ecs.placementConstraintExpression":'<p>A cluster query language expression to apply to memberOf constraints. See <a href="https://docs.aws.amazon.com/AmazonECS/latest/developerguide/cluster-query-language.html" target="_blank">AWS documentation</a> for more details.</p>',"ecs.placementStrategy":'<p>The strategy the container scheduler will be using. See <a href="http://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-placement-strategies.html" target="_blank">AWS documentation</a> for more details. </p><p>You should at least balance across availability zones</p><p>Custom placement strategies have not been implemented yet.</p>',"ecs.platformVersion":"<p>Defaults to the latest platform version.</p>","ecs.enableDeploymentCircuitBreaker":"<p>Enable circuit breaker for the ECS service.</p>","ecs.capacity.copySourceScalingPoliciesAndActions":"<p>Copy Application Autoscaling policies and their associated alarms from the previous ECS service.</p>","ecs.launchtype":"<p>Launch service tasks on your own EC2 instances or on Fargate.</p>","ecs.healthgraceperiod":"<p>How long a container will be kept alive despite the load balancer health checks, in seconds.</p>","ecs.publicip":"<p>Assign a public IP address to each task.</p>","ecs.networkMode":"<p>awsvpc is the only networking mode that allows you to use Elastic Network Interfaces (ENI). The default value converts to Bridge on Linux, and NAT on Windows.</p>","ecs.subnet":"<p>The subnet group(s) on which your server group will be deployed. All subnet groups selected must exist within the same VPC.</p>","ecs.securityGroups":"<p>The security group(s) name(s) your containers are deployed with.</p>","ecs.dockerLabels":'<p>Additional labels applied to your Docker container. This metadata can be used to identify your containers, or in conjunction with logging options. Maps directly to the <a href="https://docs.docker.com/engine/reference/commandline/run/#set-metadata-on-container--l---label---label-file"><b>--label</b> Docker flag</a>.</p> <p>Spinnaker will automatically add the spinnaker.servergroup, spinnaker.stack, spinnaker.detail labels for non-null values.</p>',"ecs.logDriver":'<p>The container\'s logging driver. This directly maps to the <a href="https://docs.docker.com/config/containers/logging/configure/#configure-the-default-logging-driver"><b>--log-driver</b> Docker flag.</a></p>',"ecs.logOptions":'<p>A map of log options. This directly maps with the <a href="https://docs.docker.com/config/containers/logging/log_tags/"><b>--log-opt</b> Docker flag </a></p>',"ecs.taskDefinition":'<p>The source of the ECS Task Definition. Task Definition contents can either be entered manually via input fields or from a selected JSON file artifact. Artifact file contents should be structured as an ECS "RegisterTaskDefinition" request.</p>',"ecs.taskDefinitionArtifact":"<p>The artifact containing the ECS Task Definition.</p>","ecs.containerMappings":"<p>The list of expected containers within the Task Definition and which container image they should use. Containers in the Task Definition which are not specified here will be registered as they appear in the artifact.</p>","ecs.containerMappingName":'<p>The name of the container. Name should match the <a href="https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_ContainerDefinition.html#ECS-Type-ContainerDefinition-name"><b>containerDefinition.name</b></a> field as it appears in the Task Definition.</p>',"ecs.containerMappingImage":"<p>The container image the named container should run.</p>","ecs.targetGroupMappings":"<p>The list of target groups through which the ECS service will receive load balancer traffic. Each target group is mapped to a container name and port within the Task Definition to specify which container should be registered to the target group.</p>","ecs.loadBalancedContainer":"<p>The container in the Task Definition that should receive traffic from the load balancer. Required if a load balancer target group has been specified.</p>","ecs.tags":"<p>The tags to apply to the task definition and the service","ecs.environmentVariables":"<p>The environment variable(s) your container are deployed with. SERVER_GROUP, CLOUD_STACK and CLOUD_DETAIL environment variables are used during deployment to identify the task and cannot be set here.</p>","ecs.serviceDiscovery":"<p>The AWS Cloud Map service discovery registries to assign to this service</p>","ecs.serviceDiscoveryRegistry":"<p>The AWS Cloud Map service to use for service discovery registration</p>","ecs.serviceDiscoveryContainerPort":"<p>The port to be used for your service discovery service. Required only for services using bridge or host network mode, and for services using awsvpc network mode and a type SRV DNS record","ecs.serviceDiscoveryContainerName":"<p>The container name value, already specified in the task definition, to be used for your service discovery service.</p>","ecs.computeOptions":'<p>Specify either a <a href="https://docs.aws.amazon.com/AmazonECS/latest/developerguide/launch_types.html" target="_blank">launch type</a> (default) or <a href="https://docs.aws.amazon.com/AmazonECS/latest/developerguide/cluster-capacity-providers.html" target="_blank">capacity providers</a> for running your ECS service.</p>',"ecs.capacityProviderStrategy":'<p>A capacity provider strategy gives you control over how your tasks use one or more capacity providers. See <a href="https://docs.aws.amazon.com/AmazonECS/latest/developerguide/cluster-capacity-providers.html#capacity-providers-concepts" target="_blank">AWS documentation</a> for more details. </p>',"ecs.capacityProviderName":"<p>The short name of the capacity provider.</p>","ecs.capacityProviderBase":"<p>Designates how many tasks, at a minimum, to run on the specified capacity provider. Only one capacity provider in a capacity provider strategy can have a <em>base</em> defined.</p>","ecs.capacityProviderWeight":"<p>Designates the relative percentage of the total number of tasks launched that should use the specified capacity provider.</p>","ecs.evaluateExpression":'<p>Whether to evaluate <a href="https://spinnaker.io/guides/user/pipeline/expressions/" target="_blank"><b>pipeline expressions</b></a> within the task definition artifact in this stage. Checking this box let\'s you evaluate your task definition artifact coming from external sources.(e.g. GitHub) </p>'};Object.keys(Ce).forEach(e=>n.register(e,Ce[e]));const we=a.providers.ecs||{};we&&(we.resetToOriginal=a.resetProvider("ecs"));const Ee="spinnaker.ecs.ecsCluster.read.service";t(Ee,[]).service("ecsClusterReader",class{listClusters(){return r("/ecs/ecsClusters").get()}describeClusters(e,t){return null!=e&&null!=t?r("/ecs/ecsClusterDescriptions").path(e).path(t).get():{}}});const De="spinnaker.ecs.iamRole.read.service";t(De,[]).service("iamRoleReader",class{listRoles(e){return r("/roles").path(e).get()}});const Ge="spinnaker.ecs.instance.details.controller";t(Ge,[V,_]).controller("ecsInstanceDetailsCtrl",["$scope","$state","$uibModal","instance","app","moniker","environment","$q","overrides",function(e,t,n,r,d,p,u,m,g){e.detailsTemplateUrl=i.getValue("ecs","instance.detailsTemplateUrl"),e.state={loading:!0,standalone:d.isStandalone,instancePort:j.get(d,"attributes.instancePort")||a.defaultInstancePort||80},e.application=d,e.moniker=p,e.environment=u;const v={cloudProvider:"ecs"};function h(){const t={};let n,a,i,s,o,p;return d.serverGroups?(d.serverGroups.data.some(function(e){return e.instances.some(function(l){if(l.id===r.instanceId)return n=l,a=e.loadBalancers,i=e.targetGroup,s=e.account,o=e.region,p=e.vpcId,t.serverGroup=e.name,t.vpcId=e.vpcId,!0})}),n||(d.loadBalancers.data.some(function(e){return e.instances.some(function(t){if(t.id===r.instanceId)return n=t,a=[e.name],s=e.account,o=e.region,p=e.vpcId,!0})||e.targetGroup.some(function(t){return t.instances.some(function(a){if(a.id===r.instanceId)return n=a,t=t.name,s=e.account,o=e.region,p=e.vpcId,!0})})}),n||d.loadBalancers.data.some(function(e){return e.serverGroups.some(function(t){return!!t.isDisabled&&t.instances.some(function(t){if(t.id===r.instanceId)return n=t,a=[e.name],s=e.account,o=e.region,p=e.vpcId,!0})})||e.targetGroup.some(function(t){t.serverGroups.some(function(t){return!!t.isDisabled&&t.instances.some(function(t){if(t.id===r.instanceId)return n=t,a=[e.name],s=e.account,o=e.region,p=e.vpcId,!0})})})}))):(n={},a=[],i=[],s=r.account,o=r.region),n&&s&&o?(n.account=s,t.account=s,t.region=o,l.addExtraDataToLatest("instances",t),c.getInstanceDetails(s,o,r.instanceId).then(t=>{if(!e.$$destroyed){if(e.state.loading=!1,function(t,n){d.isStandalone&&(t.health=n.health),t.health=t.health||[];const a=t.health.filter(function(e){return"Ecs"!==e.type||"Unknown"!==e.state}),r=le(d.loadBalancers.data);ce(a,r,t.account),n.health&&a.forEach(function(e){const t=n.health.filter(function(t){return t.type===e.type});t.length&&j.defaults(e,t[0])}),e.healthMetrics=a}(n,t),e.instance=j.defaults(t,n),e.instance.account=s,e.instance.region=o,e.instance.vpcId=p,e.instance.loadBalancers=a,e.instance.targetGroup=i,e.instance.networkInterfaces){const t=e.instance.networkInterfaces.filter(e=>!1===e.attachment.deleteOnTermination);t.length&&(e.instance.permanentIps=t.map(e=>e.privateIpAddress))}e.baseIpAddress=t.publicDnsName||t.privateIpAddress,g.instanceDetailsLoaded&&g.instanceDetailsLoaded()}},f)):(n||(e.instanceIdNotFound=r.instanceId,e.state.loading=!1),m.when(null))}function f(){e.$$destroyed||(d.isStandalone?(e.state.loading=!1,e.instanceIdNotFound=r.instanceId,e.state.notFoundStandalone=!0,l.removeLastItem("instances")):t.go("^",{allowModalToStayOpen:!0},{location:"replace"}))}this.canRegisterWithDiscovery=function(){const t=(e.instance.health||[]).filter(function(e){return"Discovery"===e.type});return!!t.length&&"OutOfService"===t[0].state},this.terminateInstance=function(){const n=e.instance,a={application:d,title:"Terminating "+n.instanceId,onTaskComplete:function(){t.includes("**.instanceDetails",{instanceId:n.instanceId})&&t.go("^")}};s.confirm({header:"Really terminate "+n.instanceId+"?",buttonText:"Terminate "+n.instanceId,account:n.account,taskMonitorConfig:a,submitMethod:function(){return o.terminateInstance(n,d,v)}})},this.terminateInstanceAndShrinkServerGroup=function(){const n=e.instance,a={application:d,title:"Terminating "+n.instanceId+" and shrinking server group",onTaskComplete:function(){t.includes("**.instanceDetails",{instanceId:n.instanceId})&&t.go("^")}};s.confirm({header:"Really terminate "+n.instanceId+" and shrink "+n.serverGroup+"?",buttonText:"Terminate "+n.instanceId+" and shrink "+n.serverGroup,account:n.account,taskMonitorConfig:a,submitMethod:function(){return o.terminateInstanceAndShrinkServerGroup(n,d,v)}})},this.enableInstanceInDiscovery=function(){const t=e.instance,n={application:d,title:"Enabling "+t.instanceId+" in discovery"};s.confirm({header:"Really enable "+t.instanceId+" in discovery?",buttonText:"Enable "+t.instanceId,account:t.account,taskMonitorConfig:n,submitMethod:function(){return o.enableInstanceInDiscovery(t,d,v)}})},this.disableInstanceInDiscovery=function(){const t=e.instance,n={application:d,title:"Disabling "+t.instanceId+" in discovery"};s.confirm({header:"Really disable "+t.instanceId+" in discovery?",buttonText:"Disable "+t.instanceId,account:t.account,taskMonitorConfig:n,submitMethod:function(){return o.disableInstanceInDiscovery(t,d,v)}})},this.hasHealthState=function(t,n){return(e.instance.health||[]).some(function(e){return e.type===t&&e.state===n})};(d.isStandalone?h():m.all([d.serverGroups.ready(),d.loadBalancers.ready()]).then(h)).then(()=>{e.$$destroyed||d.isStandalone||d.serverGroups.onRefresh(e,h)}),e.account=r.account}]);class Ae extends ue.Component{render(){const{targetGroup:e,loadBalancer:t,showServerGroups:n}=this.props,a={loadBalancerName:t.name,region:e.region,accountId:e.account,name:e.targetGroupName,vpcId:e.vpcId,provider:e.cloudProvider},r={up:void 0,down:void 0,starting:void 0,succeeded:void 0,failed:void 0,unknown:void 0,outOfService:void 0};return ue.createElement("div",{className:"target-group-container container-fluid no-padding"},ue.createElement(me,{class:"active"},ue.createElement(ge,{to:".ecsTargetGroupDetails",params:a},ue.createElement("div",{className:"clickable clickable-row row no-margin-y target-group-header"},ue.createElement("div",{className:"col-md-8 target-group-title"},e.targetGroupName)))),n&&e.serverGroups.map(t=>ue.createElement(d,{key:t,account:e.account,region:e.region,serverGroup:{account:e.account,cloudProvider:e.cloudProvider,cluster:t,instanceCounts:r,instances:e.instances,name:t,type:e.type,region:e.region},showInstances:!1})))}}class Te extends ue.Component{shouldComponentUpdate(e){return e.showInstances!==this.props.showInstances||e.showServerGroups!==this.props.showServerGroups||e.loadBalancer!==this.props.loadBalancer||(()=>!W((e.serverGroups||[]).map(e=>e.name),(this.props.serverGroups||[]).map(e=>e.name)))()||(()=>!W((e.loadBalancer.targetGroups||[]).map(e=>e.targetGroupName),(this.props.loadBalancer.targetGroups||[]).map(e=>e.targetGroupName)))()}render(){const{loadBalancer:e,showInstances:t,showServerGroups:n}=this.props,a=e.targetGroups.map(a=>ue.createElement(Ae,{key:a.targetGroupName,loadBalancer:e,targetGroup:a,showInstances:t,showServerGroups:n}));return ue.createElement("div",{className:"cluster-container"},a)}}class Ne extends ue.Component{constructor(e){super(e)}getTargetGroupNameFromArn(e){const t=e.split("/");return t.length<0?e:t[1]}render(){const{port:e,protocol:t,defaultActions:n}=this.props.listener;return ue.createElement("div",null,ue.createElement("h4",null,t,":",e),ue.createElement("div",{style:{paddingLeft:10}},ue.createElement("i",null,"default actions"),ue.createElement("ul",null,n.map((e,t)=>"forward"==e.type?ue.createElement("li",{key:t},"→",ue.createElement("i",{className:"fa fa-fw fa-crosshairs icon","aria-hidden":"true"}),ue.createElement("span",null,e.targetGroupArn||e.forwardConfig.targetGroups.map(e=>this.getTargetGroupNameFromArn(e.targetGroupArn)))):ue.createElement("li",{key:t},e.type,":"," ",e.redirectConfig.statusCode||e.fixedResponseConfig.statusCode||e.authenticateOidcConfig.clientId||e.authenticateCognitoActionConfig.userPoolDomain)))))}}class Pe extends ue.Component{constructor(e){super(e),this.state={loading:!0,loadBalancer:void 0,refreshListenerUnsubscribe:()=>{}},e.app.getDataSource("loadBalancers").ready().then(()=>this.extractLoadBalancer())}componentWillUnmount(){this.state.refreshListenerUnsubscribe()}extractLoadBalancer(){const{name:e,region:t}=this.props.loadBalancer,n=this.props.app.getDataSource("loadBalancers").data.find(n=>n.name===e&&n.account===this.props.loadBalancer.accountId&&n.region===t);this.setState({loading:!1,loadBalancer:n}),this.state.refreshListenerUnsubscribe(),n?this.setState({refreshListenerUnsubscribe:this.props.app.getDataSource("loadBalancers").onRefresh(null,()=>this.extractLoadBalancer())}):this.setState({refreshListenerUnsubscribe:()=>{}})}render(){const e=this.props.loadBalancer.name,{loadBalancer:t,loading:n}=this.state,{accountId:a}=this.props,r=ue.createElement("div",{className:"close-button"},ue.createElement(ge,{to:"^"},ue.createElement("span",{className:"glyphicon glyphicon-remove"})));return ue.createElement("div",{className:"details-panel"},n&&ue.createElement("div",{className:"header"},r,ue.createElement("div",{className:"horizontal center middle"},ue.createElement(p,{size:"small"}))),!n&&ue.createElement("div",{className:"header"},r,ue.createElement("div",{className:"header-text horizontal middle"},ue.createElement("i",{className:"fa icon-sitemap"}),ue.createElement("h3",{className:"horizontal middle space-between flex-1"},e))),!n&&!t&&ue.createElement("div",{className:"content"},ue.createElement("div",{className:"content-section"},ue.createElement("div",{className:"content-body text-center"},ue.createElement("h3",null,"Load balancer not found.")))),!n&&t&&ue.createElement("div",{className:"content"},ue.createElement(u,{heading:"Load Balancer Details",defaultExpanded:!0},ue.createElement("dl",{className:"dl-horizontal dl-narrow"},ue.createElement("dt",null,"Created"),ue.createElement("dd",null,m(t.createdTime)),ue.createElement("dt",null,"In"),ue.createElement("dd",null,ue.createElement(g,{account:a}),ue.createElement("br",null),t.region),ue.createElement("dt",null,"VPC"),ue.createElement("dd",null,t.vpcId),ue.createElement("dt",null,"Type"),ue.createElement("dd",null,t.loadBalancerType),ue.createElement("dt",null,"IP Type"),ue.createElement("dd",null,t.ipAddressType)),ue.createElement("dl",{className:"horizontal-when-filters-collapsed"},ue.createElement("dt",null,"Availability Zones"),ue.createElement("dd",null,ue.createElement("ul",null,t.availabilityZones.map(e=>ue.createElement("li",{key:e},e))))),ue.createElement("dl",{className:"horizontal-when-filters-collapsed"},ue.createElement("dt",null,"Target Groups"),ue.createElement("dd",null,ue.createElement("ul",null,t.targetGroups.map(e=>ue.createElement("li",{key:e.targetGroupName},ue.createElement(me,{class:"active"},ue.createElement(ge,{to:"^.ecsTargetGroupDetails",params:{loadBalancerName:t.name,region:t.region,accountId:t.account,name:e.targetGroupName,vpcId:e.vpcId,provider:t.cloudProvider}},ue.createElement("a",null,e.targetGroupName)))))))),ue.createElement("dl",{className:"horizontal-when-filters-collapsed"},ue.createElement("dt",null,"DNS Name"),ue.createElement("dd",null,ue.createElement("a",{target:"_blank",href:"http://"+t.dnsname},t.dnsname)))),ue.createElement(u,{heading:"Status",defaultExpanded:!1},ue.createElement("span",null,"Select a target group to check the instance health status from the view of its server groups.")),ue.createElement(u,{heading:"Listeners",defaultExpanded:!1},t.listeners?t.listeners.map((e,t)=>ue.createElement("div",{key:t},ue.createElement("span",null,ue.createElement(Ne,{listener:e})))):ue.createElement("li",null,"No listeners provided.")),ue.createElement(u,{heading:"Firewalls",defaultExpanded:!1},ue.createElement("ul",null,t.securityGroups?t.securityGroups.map(e=>ue.createElement("li",{key:e},e)):ue.createElement("li",null,"No security groups provided."))),ue.createElement(u,{heading:"Subnets",defaultExpanded:!1},ue.createElement("ul",null,t.subnets.map(e=>ue.createElement("li",{key:e},e))))))}}class Ie extends ue.Component{constructor(e){super(e),this.state={loading:!0,targetGroup:void 0,loadBalancer:void 0,refreshListenerUnsubscribe:()=>{}},e.app.getDataSource("loadBalancers").ready().then(()=>this.extractTargetGroup())}componentWillUnmount(){this.state.refreshListenerUnsubscribe()}extractTargetGroup(){const{loadBalancerName:e,region:t,targetGroupName:n}=this.props.targetGroup,a=this.props.app.getDataSource("loadBalancers").data.find(n=>n.name===e&&n.account===this.props.accountId&&n.region===t);if(this.setState({loadBalancer:a}),this.state.refreshListenerUnsubscribe(),a){const e=a.targetGroups.find(e=>e.targetGroupName===n);e||this.setState({loading:!1,targetGroup:null}),e&&(this.setState({loading:!1,targetGroup:e}),e?this.setState({refreshListenerUnsubscribe:this.props.app.getDataSource("loadBalancers").onRefresh(null,()=>this.extractTargetGroup())}):this.setState({refreshListenerUnsubscribe:()=>{}}))}else this.setState({loading:!1,targetGroup:null})}render(){const{name:e,accountId:t}=this.props,n=this.props.targetGroup.region,{targetGroup:a,loadBalancer:r,loading:i}=this.state,s=ue.createElement("div",{className:"close-button"},ue.createElement(ge,{to:"^"},ue.createElement("span",{className:"glyphicon glyphicon-remove"})));return ue.createElement("div",{className:"details-panel"},i&&ue.createElement("div",{className:"header"},s,ue.createElement("div",{className:"horizontal center middle"},ue.createElement(p,{size:"small"}))),!i&&ue.createElement("div",{className:"header"},ue.createElement("div",{className:"header-text horizontal middle"},ue.createElement("i",{className:"fa fa-crosshairs icon","aria-hidden":"true"}),ue.createElement("h3",{className:"horizontal middle space-between flex-1"},e))),!i&&!a&&ue.createElement("div",{className:"content"},ue.createElement("div",{className:"content-section"},ue.createElement("div",{className:"content-body text-center"},ue.createElement("h3",null,"Target group not found.")))),!i&&a&&ue.createElement("div",{className:"content"},ue.createElement(u,{heading:"Target Group Details",defaultExpanded:!0},ue.createElement("dl",{className:"dl-horizontal dl-narrow"},ue.createElement("dt",null,"In"),ue.createElement("dd",null,ue.createElement(g,{account:t}),ue.createElement("br",null),a.region),ue.createElement("dt",null,"VPC"),ue.createElement("dd",null,a.vpcId),ue.createElement("dt",null,"Protocol"),ue.createElement("dd",null,a.protocol),ue.createElement("dt",null,"Port"),ue.createElement("dd",null,a.port),ue.createElement("dt",null,"Target Type"),ue.createElement("dd",null,a.targetType.toUpperCase())),ue.createElement("dl",{className:"horizontal-when-filters-collapsed"},ue.createElement("dt",null,"Load Balancers"),ue.createElement("dd",null,ue.createElement("ul",{className:"collapse-margin-on-filter-collapse"},a.loadBalancerNames?a.loadBalancerNames.map((e,t)=>ue.createElement("li",{key:t},e)):ue.createElement("li",null,"No load balncers provided.")))),ue.createElement("dl",{className:"horizontal-when-filters-collapsed"},ue.createElement("dt",null,"Load Balancer DNS Name"),ue.createElement("dd",null,ue.createElement("a",{target:"_blank",href:"http://"+r.dnsname},r.dnsname))),ue.createElement("dl",{className:"horizontal-when-filters-collapsed"},ue.createElement("dt",null,"Server Groups"),ue.createElement("dd",null,ue.createElement("ul",{className:"collapse-margin-on-filter-collapse"},a.serverGroups.map((e,a)=>ue.createElement("li",{key:a},ue.createElement(me,{class:"active"},ue.createElement(ge,{to:"^.serverGroup",params:{region:n,accountId:t,serverGroup:e,provider:"ecs"}},ue.createElement("a",null,e))))))))),ue.createElement(u,{heading:"Health Checks",defaultExpanded:!1},ue.createElement("dl",{className:"horizontal-when-filters-collapsed"},ue.createElement("dt",null,"Target"),ue.createElement("dd",null,a.healthCheckProtocol,":",a.healthCheckPort,a.healthCheckPath),ue.createElement("dt",null,"Timeout"),ue.createElement("dd",null,a.healthCheckTimeoutSeconds," seconds"),ue.createElement("dt",null,"Interval"),ue.createElement("dd",null,a.healthCheckIntervalSeconds," seconds"),ue.createElement("dt",null,"Healthy Threshold"),ue.createElement("dd",null,a.healthyThresholdCount),ue.createElement("dt",null,"Unhealthy Threshold"),ue.createElement("dd",null,a.unhealthyThresholdCount),ue.createElement("dt",null,"Matcher"),ue.createElement("dd",null,"HTTP Code(s): ",a&&a.matcher?a.matcher.httpCode:"None"))),ue.createElement(u,{heading:"Attributes",defaultExpanded:!1},ue.createElement("dl",null,ue.createElement("dt",null,"Deregistration Delay Timeout"),ue.createElement("dd",null,a.attributes["deregistration_delay.timeout_seconds"]||0," seconds"),ue.createElement("dt",null,"Stickiness Enabled"),ue.createElement("dd",null,a.attributes["stickiness.enabled"]||"N/A")))))}}class ze{constructor(e){this.$q=e}normalizeLoadBalancer(e){return e.targetGroups.forEach(t=>{if(t.region=e.region,t.account=e.account,t.cloudProvider=e.cloudProvider,e.targetGroupServices){const n=e.targetGroupServices;t.serverGroups=n[t.targetGroupArn]}}),this.$q.resolve(e)}}ze.$inject=["$q"];const xe="spinnaker.ecs.loadBalancer.targetGroup.states";t(xe,[v]).config(["applicationStateProvider",e=>{const t={name:"ecsTargetGroupDetails",url:"/ecsTargetGroupDetails/:provider/:accountId/:region/:vpcId/:loadBalancerName/:name",params:{vpcId:{value:null,squash:!0}},views:{"detail@../insight":{component:Ie,$type:"react"}},resolve:{accountId:["$stateParams",e=>e.accountId],name:["$stateParams",e=>e.name],provider:["$stateParams",e=>e.provider],targetGroup:["$stateParams",e=>({loadBalancerName:e.loadBalancerName,targetGroupName:e.name,accountId:e.accountId,region:e.region,vpcId:e.vpcId})]},data:{pageTitleDetails:{title:"Target Group Details",nameParam:"name",accountParam:"accountId",regionParam:"region"}}};e.addInsightDetailState(t)}]);const Me="spinnaker.ecs.metricAlarm.read.service";t(Me,[]).service("metricAlarmReader",class{listMetricAlarms(){return r("/ecs/cloudMetrics/alarms").get()}});const Re="spinnaker.ecs.pipeline.stage.ecs.destroyAsgStage";t(Re,[]).config(function(){h.pipeline.registerStage({provides:"destroyServerGroup",alias:"destroyAsg",cloudProvider:"ecs",templateUrl:"ecs/src/pipeline/stages/destroyAsg/destroyAsgStage.html",executionStepLabelUrl:"ecs/src/pipeline/stages/destroyAsg/destroyAsgStepLabel.html",accountExtractor:e=>[e.context.credentials],configAccountExtractor:e=>[e.credentials],validators:[{type:"targetImpedance",message:"This pipeline will attempt to destroy a server group without deploying a new version into the same cluster."},{type:"requiredField",fieldName:"cluster"},{type:"requiredField",fieldName:"target"},{type:"requiredField",fieldName:"regions"},{type:"requiredField",fieldName:"credentials",fieldLabel:"account"}]})}).controller("ecsDestroyAsgStageCtrl",["$scope",function(e){const t=e.stage;e.state={accounts:!1,regionsLoaded:!1},f.listAccounts("ecs").then(function(t){e.accounts=t,e.state.accounts=!0}),e.regions=["us-east-1","us-west-1","eu-west-1","us-west-2"],e.targets=y.TARGET_LIST,t.regions=t.regions||[],t.cloudProvider="ecs",!t.credentials&&e.application.defaultCredentials.ecs&&(t.credentials=e.application.defaultCredentials.ecs),!t.regions.length&&e.application.defaultRegions.ecs&&t.regions.push(e.application.defaultRegions.ecs),t.target||(t.target=e.targets[0].val)}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/pipeline/stages/destroyAsg/destroyAsgStage.html",'<div ng-controller="ecsDestroyAsgStageCtrl as destroyAsgStageCtrl" class="form-horizontal">\n <div ng-if="!pipeline.strategy">\n <account-region-cluster-selector application="application" component="stage" accounts="accounts">\n </account-region-cluster-selector>\n </div>\n <stage-config-field label="Target">\n <target-select model="stage" options="targets"></target-select>\n </stage-config-field>\n</div>\n')}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/pipeline/stages/destroyAsg/destroyAsgStepLabel.html",'<span class="task-label"> Destroy Server Group: {{step.context.serverGroupName}} ({{step.context.region}}) </span>\n')}]);const $e="spinnaker.ecs.pipeline.stage.disableAsgStage";t($e,[]).config(function(){h.pipeline.registerStage({provides:"disableServerGroup",alias:"disableAsg",cloudProvider:"ecs",templateUrl:"ecs/src/pipeline/stages/disableAsg/disableAsgStage.html",executionDetailsUrl:b.disableAsgExecutionDetails,executionStepLabelUrl:"ecs/src/pipeline/stages/disableAsg/disableAsgStepLabel.html",validators:[{type:"targetImpedance",message:"This pipeline will attempt to disable a server group without deploying a new version into the same cluster."},{type:"requiredField",fieldName:"cluster"},{type:"requiredField",fieldName:"target"},{type:"requiredField",fieldName:"regions"},{type:"requiredField",fieldName:"credentials",fieldLabel:"account"}]})}).controller("ecsDisableAsgStageCtrl",["$scope",function(e){const t=e.stage;e.state={accounts:!1,regionsLoaded:!1},f.listAccounts("ecs").then(function(t){e.accounts=t,e.state.accounts=!0}),e.targets=y.TARGET_LIST,t.regions=t.regions||[],t.cloudProvider="ecs",t.isNew&&e.application.attributes.platformHealthOnlyShowOverride&&e.application.attributes.platformHealthOnly&&(t.interestingHealthProviderNames=["Ecs"]),!t.credentials&&e.application.defaultCredentials.ecs&&(t.credentials=e.application.defaultCredentials.ecs),!t.regions.length&&e.application.defaultRegions.ecs&&t.regions.push(e.application.defaultRegions.ecs),t.target||(t.target=e.targets[0].val)}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/pipeline/stages/disableAsg/disableAsgStage.html",'<div ng-controller="ecsDisableAsgStageCtrl as disableAsgStageCtrl" class="form-horizontal">\n <div ng-if="!pipeline.strategy">\n <account-region-cluster-selector application="application" component="stage" accounts="accounts">\n </account-region-cluster-selector>\n </div>\n <stage-config-field label="Target">\n <target-select model="stage" options="targets"></target-select>\n </stage-config-field>\n <stage-platform-health-override application="application" stage="stage" platform-health-type="\'Ecs\'">\n </stage-platform-health-override>\n</div>\n')}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/pipeline/stages/disableAsg/disableAsgStepLabel.html",'<span class="task-label"> Disable Server Group: {{step.context.serverGroupName}} ({{step.context.region}}) </span>\n')}]);const Be="spinnaker.ecs.pipeline.stage.disableClusterStage";t(Be,[]).config(function(){h.pipeline.registerStage({provides:"disableCluster",cloudProvider:"ecs",templateUrl:"ecs/src/pipeline/stages/disableCluster/disableClusterStage.html",validators:[{type:"requiredField",fieldName:"cluster"},{type:"requiredField",fieldName:"remainingEnabledServerGroups",fieldLabel:"Keep [X] enabled Server Groups"},{type:"requiredField",fieldName:"regions"},{type:"requiredField",fieldName:"credentials",fieldLabel:"account"}]})}).controller("ecsDisableClusterStageCtrl",["$scope",function(e){const t=this,n=e.stage;e.state={accounts:!1,regionsLoaded:!1},f.listAccounts("ecs").then(function(t){e.accounts=t,e.state.accounts=!0}),t.reset=()=>{t.accountUpdated(),t.resetSelectedCluster()},n.regions=n.regions||[],n.cloudProvider="ecs",n.isNew&&e.application.attributes.platformHealthOnlyShowOverride&&e.application.attributes.platformHealthOnly&&(n.interestingHealthProviderNames=["Ecs"]),!n.credentials&&e.application.defaultCredentials.ecs&&(n.credentials=e.application.defaultCredentials.ecs),!n.regions.length&&e.application.defaultRegions.ecs&&n.regions.push(e.application.defaultRegions.ecs),void 0===n.remainingEnabledServerGroups&&(n.remainingEnabledServerGroups=1),t.pluralize=function(e,t){return 1===t?e:e+"s"},void 0===n.preferLargerOverNewer&&(n.preferLargerOverNewer="false"),n.preferLargerOverNewer=n.preferLargerOverNewer.toString()}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/pipeline/stages/disableCluster/disableClusterStage.html",'<div ng-controller="ecsDisableClusterStageCtrl as disableClusterStageCtrl" class="form-horizontal">\n <div ng-if="!pipeline.strategy">\n <account-region-cluster-selector application="application" component="stage" accounts="accounts">\n </account-region-cluster-selector>\n </div>\n <stage-config-field label="Disable Options">\n <div class="form-inline">\n Keep the\n <input\n type="number"\n min="0"\n required\n ng-model="stage.remainingEnabledServerGroups"\n class="form-control input-sm"\n style="width: 50px"\n />\n <select class="form-control input-sm" ng-model="stage.preferLargerOverNewer" style="width: 100px">\n <option value="true">largest</option>\n <option value="false">newest</option>\n </select>\n {{disableClusterStageCtrl.pluralize(\'server group\', stage.remainingEnabledServerGroups)}} enabled.\n </div>\n </stage-config-field>\n <stage-platform-health-override application="application" stage="stage" platform-health-type="\'Ecs\'">\n </stage-platform-health-override>\n</div>\n')}]);const Fe="spinnaker.ecs.pipeline.stage.enableAsgStage";t(Fe,[]).config(function(){h.pipeline.registerStage({provides:"enableServerGroup",alias:"enableAsg",cloudProvider:"ecs",templateUrl:"ecs/src/pipeline/stages/enableAsg/enableAsgStage.html",executionStepLabelUrl:"ecs/src/pipeline/stages/enableAsg/enableAsgStepLabel.html",validators:[{type:"requiredField",fieldName:"cluster"},{type:"requiredField",fieldName:"target"},{type:"requiredField",fieldName:"regions"},{type:"requiredField",fieldName:"credentials",fieldLabel:"account"}]})}).controller("ecsEnableAsgStageCtrl",["$scope",function(e){const t=this,n=e.stage;e.state={accounts:!1,regionsLoaded:!1},f.listAccounts("ecs").then(function(t){e.accounts=t,e.state.accounts=!0}),t.reset=()=>{t.accountUpdated(),t.resetSelectedCluster()},e.targets=y.TARGET_LIST,n.regions=n.regions||[],n.cloudProvider="ecs",n.isNew&&e.application.attributes.platformHealthOnlyShowOverride&&e.application.attributes.platformHealthOnly&&(n.interestingHealthProviderNames=["Ecs"]),!n.credentials&&e.application.defaultCredentials.ecs&&(n.credentials=e.application.defaultCredentials.ecs),!n.regions.length&&e.application.defaultRegions.ecs&&n.regions.push(e.application.defaultRegions.ecs),n.target||(n.target=e.targets[0].val),e.$watch("stage.credentials",e.accountUpdated)}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/pipeline/stages/enableAsg/enableAsgStage.html",'<div ng-controller="ecsEnableAsgStageCtrl as enableAsgStageCtrl" class="form-horizontal">\n <div ng-if="!pipeline.strategy">\n <account-region-cluster-selector application="application" component="stage" accounts="accounts">\n </account-region-cluster-selector>\n </div>\n <stage-config-field label="Target">\n <target-select model="stage" options="targets"></target-select>\n </stage-config-field>\n <stage-platform-health-override application="application" stage="stage" platform-health-type="\'Ecs\'">\n </stage-platform-health-override>\n</div>\n')}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/pipeline/stages/enableAsg/enableAsgStepLabel.html",'<span class="task-label"> Enable Server Group: {{step.context.serverGroupName}} ({{step.context.region}}) </span>\n')}]);const Le="spinnaker.ecs.pipeline.stage.findImageFromTagsStage";t(Le,[]).config(function(){h.pipeline.registerStage({provides:"findImageFromTags",cloudProvider:"ecs",templateUrl:"ecs/src/pipeline/stages/findImageFromTags/findImageFromTagsStage.html",executionDetailsUrl:"ecs/src/pipeline/stages/findImageFromTags/findImageFromTagsExecutionDetails.html",executionConfigSections:["findImageConfig","taskStatus"],validators:[{type:"requiredField",fieldName:"imageLabelOrSha"}]})}).controller("ecsFindImageFromTagsStageCtrl",["$scope",function(e){e.stage.cloudProvider=e.stage.cloudProvider||"ecs"}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/pipeline/stages/findImageFromTags/findImageFromTagsStage.html",'<div ng-controller="ecsFindImageFromTagsStageCtrl as findImageFromTagsCtrl" class="form-horizontal">\n <stage-config-field label="Full Docker Image path (label or SHA-256)">\n <input type="text" class="form-control input-sm" ng-model="stage.imageLabelOrSha" />\n </stage-config-field>\n</div>\n\n<div>\n <h5>Example value: <i>12345678901.dkr.ecr.us-west-2.amazonaws.com/continuous-delivery:latest</i></h5>\n</div>\n')}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/pipeline/stages/findImageFromTags/findImageFromTagsExecutionDetails.html",'<div ng-controller="BaseExecutionDetailsCtrl">\n <execution-details-section-nav sections="configSections"></execution-details-section-nav>\n <div class="step-section-details" ng-if="detailsSection === \'findImageConfig\'">\n <div class="row">\n <div class="col-md-12">\n <dl class="dl-narrow dl-horizontal">\n <dt if-multiple-providers>Provider</dt>\n <dd if-multiple-providers>ECS</dd>\n </dl>\n </div>\n </div>\n <stage-failure-message stage="stage" message="stage.failureMessage"></stage-failure-message>\n\n <div class="row" ng-if="stage.context.amiDetails">\n <div class="col-md-12">\n <div class="well alert alert-info">\n <h4>Results</h4>\n <dl ng-repeat="image in stage.context.amiDetails" class="dl-narrow dl-horizontal">\n <dt>Region</dt>\n <dd>{{image.region}}</dd>\n <dt>Image ID</dt>\n <dd>{{image.imageId}}</dd>\n <dt>Unique ID</dt>\n <dd>{{image.imageName}}</dd>\n </dl>\n </div>\n </div>\n </div>\n </div>\n\n <div class="step-section-details" ng-if="detailsSection === \'taskStatus\'">\n <div class="row">\n <execution-step-details item="stage"></execution-step-details>\n </div>\n </div>\n</div>\n')}]);const Oe="spinnaker.ecs.pipeline.stage.ecs.resizeAsgStage";t(Oe,[]).config(function(){h.pipeline.registerStage({provides:"resizeServerGroup",alias:"resizeAsg",cloudProvider:"ecs",templateUrl:"ecs/src/pipeline/stages/resizeAsg/resizeAsgStage.html",executionConfigSections:["resizeServerGroupConfig","taskStatus"],executionStepLabelUrl:"ecs/src/pipeline/stages/resizeAsg/resizeAsgStepLabel.html",accountExtractor:e=>[e.context.credentials],configAccountExtractor:e=>[e.credentials],validators:[{type:"targetImpedance",message:"This pipeline will attempt to resize a server group without deploying a new version into the same cluster."},{type:"requiredField",fieldName:"target"},{type:"requiredField",fieldName:"action"},{type:"requiredField",fieldName:"regions"},{type:"requiredField",fieldName:"cluster"},{type:"requiredField",fieldName:"credentials",fieldLabel:"account"}]})}).controller("ecsResizeAsgStageCtrl",["$scope",function(e){const t=e.stage;e.viewState={accountsLoaded:!1,regionsLoaded:!1},f.listAccounts("ecs").then(function(t){e.accounts=t,e.viewState.accountsLoaded=!0}),e.resizeTargets=y.TARGET_LIST,e.scaleActions=[{label:"Scale Up",val:"scale_up"},{label:"Scale Down",val:"scale_down"},{label:"Scale to Cluster Size",val:"scale_to_cluster"},{label:"Scale to Exact Size",val:"scale_exact"}],e.resizeTypes=[{label:"Percentage",val:"pct"},{label:"Incremental",val:"incr"}],t.capacity=t.capacity||{},t.regions=t.regions||[],t.target=t.target||e.resizeTargets[0].val,t.action=t.action||e.scaleActions[0].val,t.resizeType=t.resizeType||e.resizeTypes[0].val,void 0===t.targetHealthyDeployPercentage&&(t.targetHealthyDeployPercentage=100),t.action||"exact"!==t.resizeType||(t.action="scale_exact"),t.cloudProvider="ecs",t.isNew&&e.application.attributes.platformHealthOnlyShowOverride&&e.application.attributes.platformHealthOnly&&(t.interestingHealthProviderNames=["Ecs"]),!t.credentials&&e.application.defaultCredentials.ecs&&(t.credentials=e.application.defaultCredentials.ecs),!t.regions.length&&e.application.defaultRegions.ecs&&t.regions.push(e.application.defaultRegions.ecs),this.updateResizeType=function(){"scale_exact"===t.action?(t.resizeType="exact",delete t.scalePct,delete t.scaleNum):(t.capacity={},"pct"===t.resizeType?delete t.scaleNum:(t.resizeType="incr",delete t.scalePct,t.scaleNum=t.scaleNum||0))}}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/pipeline/stages/resizeAsg/resizeAsgStage.html",'<div ng-controller="ecsResizeAsgStageCtrl as resizeAsgStageCtrl">\n <div ng-if="!pipeline.strategy">\n <div ng-if="!viewState.accountsLoaded">\n <h4 class="text-center">\n <span us-spinner="{radius:20, width:6, length: 12}"></span>\n </h4>\n </div>\n <div ng-if="viewState.accountsLoaded">\n <account-region-cluster-selector application="application" component="stage" accounts="accounts">\n </account-region-cluster-selector>\n </div>\n </div>\n <stage-config-field label="Target">\n <target-select model="stage" options="resizeTargets"></target-select>\n </stage-config-field>\n <stage-config-field label="Action" help-key="pipeline.config.resizeAsg.action">\n <select\n class="form-control input-sm"\n required\n ng-model="stage.action"\n ng-change="resizeAsgStageCtrl.updateResizeType()"\n ng-options="a.val as a.label for a in scaleActions"\n >\n <option>Select an action...</option>\n </select>\n </stage-config-field>\n <div ng-if="stage.action !== \'scale_exact\'">\n <stage-config-field label="{{stage.action === \'scale_to_cluster\' ? \'Additional Capacity\' : \'Type\'}}">\n <select\n class="form-control input-sm"\n required\n ng-model="stage.resizeType"\n ng-change="resizeAsgStageCtrl.updateResizeType()"\n ng-options="t.val as t.label for t in resizeTypes"\n >\n <option>Select an action...</option>\n </select>\n </stage-config-field>\n <div ng-if="stage.resizeType === \'pct\'">\n <stage-config-field label="Resize Percentage">\n <input type="number" min="0" ng-model="stage.scalePct" class="form-control input-sm" style="width: 80px" />\n <div>\n <em class="subinput-note"\n >This is the percentage by which the target server group\'s capacity will be increased</em\n >\n </div>\n </stage-config-field>\n </div>\n <div ng-if="stage.resizeType === \'incr\'">\n <stage-config-field label="Resize-by Amount">\n <input type="number" min="0" ng-model="stage.scaleNum" class="form-control input-sm" style="width: 80px" />\n <div>\n <em class="subinput-note"\n >This is the exact amount by which the target server group\'s capacity will be increased</em\n >\n </div>\n </stage-config-field>\n </div>\n </div>\n <div ng-if="stage.action === \'scale_exact\'">\n <stage-config-field class="small">\n <div class="row">\n <div class="col-md-3">Min</div>\n <div class="col-md-3">Max</div>\n <div class="col-md-3">Desired</div>\n </div>\n </stage-config-field>\n <stage-config-field label="Match Capacity">\n <div class="row">\n <div class="col-md-3">\n <input type="number" ng-model="stage.capacity.min" class="form-control input-sm" />\n </div>\n <div class="col-md-3">\n <input type="number" ng-model="stage.capacity.max" class="form-control input-sm" />\n </div>\n <div class="col-md-3">\n <input type="number" ng-model="stage.capacity.desired" class="form-control input-sm" />\n </div>\n </div>\n </stage-config-field>\n <stage-config-field>\n <em class="subinput-note">This is the exact amount to which the target server group will be scaled</em>\n </stage-config-field>\n </div>\n <stage-platform-health-override application="application" stage="stage" platform-health-type="\'Ecs\'">\n </stage-platform-health-override>\n</div>\n')}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/pipeline/stages/resizeAsg/resizeAsgStepLabel.html",'<span class="task-label"> Resize Server Group: {{step.context.serverGroupName}} ({{step.context.region}}) </span>\n')}]);const Ue="spinnaker.ecs.pipeline.stage.scaleDownClusterStage";t(Ue,[]).config(function(){h.pipeline.registerStage({provides:"scaleDownCluster",cloudProvider:"ecs",templateUrl:"ecs/src/pipeline/stages/scaleDownCluster/scaleDownClusterStage.html",accountExtractor:e=>[e.context.credentials],configAccountExtractor:e=>[e.credentials],validators:[{type:"requiredField",fieldName:"cluster"},{type:"requiredField",fieldName:"remainingFullSizeServerGroups",fieldLabel:"Keep [X] full size Server Groups"},{type:"requiredField",fieldName:"regions"},{type:"requiredField",fieldName:"credentials",fieldLabel:"account"}],strategy:!0})}).controller("ecsScaleDownClusterStageCtrl",["$scope",function(e){const t=e.stage;e.state={accounts:!1,regionsLoaded:!1},f.listAccounts("ecs").then(function(t){e.accounts=t,e.state.accounts=!0}),t.regions=t.regions||[],t.cloudProvider="ecs",!t.credentials&&e.application.defaultCredentials.ecs&&(t.credentials=e.application.defaultCredentials.ecs),!t.regions.length&&e.application.defaultRegions.ecs&&t.regions.push(e.application.defaultRegions.ecs),void 0===t.remainingFullSizeServerGroups&&(t.remainingFullSizeServerGroups=1),void 0===t.allowScaleDownActive&&(t.allowScaleDownActive=!1),this.pluralize=function(e,t){return 1===t?e:e+"s"},void 0===t.preferLargerOverNewer&&(t.preferLargerOverNewer="false"),t.preferLargerOverNewer=t.preferLargerOverNewer.toString()}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/pipeline/stages/scaleDownCluster/scaleDownClusterStage.html",'<div ng-controller="ecsScaleDownClusterStageCtrl as scaleDownClusterStageCtrl" class="form-horizontal">\n <div ng-if="!pipeline.strategy">\n <account-region-cluster-selector application="application" component="stage" accounts="accounts">\n </account-region-cluster-selector>\n </div>\n <stage-config-field label="Scale Down Options">\n <div class="form-inline">\n <p>\n Keep the\n <input\n type="number"\n min="0"\n required\n ng-model="stage.remainingFullSizeServerGroups"\n class="form-control input-sm"\n style="width: 50px"\n />\n <select class="form-control input-sm" ng-model="stage.preferLargerOverNewer" style="width: 100px">\n <option value="true">largest</option>\n <option value="false">newest</option>\n </select>\n {{scaleDownClusterStageCtrl.pluralize(\'server group\', stage.remainingFullSizeServerGroups)}} at current size.\n </p>\n <p>The remaining server groups will be scaled down to zero instances.</p>\n </div>\n </stage-config-field>\n <div class="form-group">\n <div class="col-md-offset-3 col-md-6 checkbox">\n <label>\n <input type="checkbox" ng-model="stage.allowScaleDownActive" />\n Allow scale down of active server groups\n </label>\n </div>\n </div>\n</div>\n')}]);const qe="spinnaker.ecs.pipeline.stage.ecs.shrinkClusterStage";t(qe,[]).config(function(){h.pipeline.registerStage({provides:"shrinkCluster",cloudProvider:"ecs",templateUrl:"ecs/src/pipeline/stages/shrinkCluster/shrinkClusterStage.html",accountExtractor:e=>[e.context.credentials],configAccountExtractor:e=>[e.credentials],validators:[{type:"requiredField",fieldName:"cluster"},{type:"requiredField",fieldName:"shrinkToSize",fieldLabel:"shrink to [X] Server Groups"},{type:"requiredField",fieldName:"regions"},{type:"requiredField",fieldName:"credentials",fieldLabel:"account"}]})}).controller("ecsShrinkClusterStageCtrl",["$scope",function(e){const t=e.stage;e.state={accounts:!1,regionsLoaded:!1},f.listAccounts("ecs").then(function(t){e.accounts=t,e.state.accounts=!0}),t.regions=t.regions||[],t.cloudProvider="ecs",!t.credentials&&e.application.defaultCredentials.ecs&&(t.credentials=e.application.defaultCredentials.ecs),!t.regions.length&&e.application.defaultRegions.ecs&&t.regions.push(e.application.defaultRegions.ecs),void 0===t.shrinkToSize&&(t.shrinkToSize=1),void 0===t.allowDeleteActive&&(t.allowDeleteActive=!1),this.pluralize=function(e,t){return 1===t?e:e+"s"},void 0===t.retainLargerOverNewer&&(t.retainLargerOverNewer="false"),t.retainLargerOverNewer=t.retainLargerOverNewer.toString()}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/pipeline/stages/shrinkCluster/shrinkClusterStage.html",'<div ng-controller="ecsShrinkClusterStageCtrl as shrinkClusterStageCtrl" class="form-horizontal">\n <div ng-if="!pipeline.strategy">\n <account-region-cluster-selector application="application" component="stage" accounts="accounts">\n </account-region-cluster-selector>\n </div>\n <stage-config-field label="Shrink Options">\n <div class="form-inline">\n Shrink to\n <input\n type="number"\n min="0"\n required\n ng-model="stage.shrinkToSize"\n class="form-control input-sm"\n style="width: 50px"\n />\n {{shrinkClusterStageCtrl.pluralize(\'server group\', stage.shrinkToSize)}}, keeping the\n <select class="form-control input-sm" ng-model="stage.retainLargerOverNewer" style="width: 100px">\n <option value="true">largest</option>\n <option value="false">newest</option>\n </select>\n </div>\n </stage-config-field>\n <div class="form-group">\n <div class="col-md-offset-3 col-md-6 checkbox">\n <label>\n <input type="checkbox" ng-model="stage.allowDeleteActive" />\n Allow deletion of active server groups\n </label>\n </div>\n </div>\n <stage-platform-health-override application="application" stage="stage" platform-health-type="\'Ecs\'">\n </stage-platform-health-override>\n</div>\n')}]);const He="spinnaker.ecs.placementStrategyService.service";t(He,[]).service("placementStrategyService",class{getPredefinedStrategy(e){return"AZ Balanced Spread"===e?this.getAzBalancedSpreadStrategy():"AZ Balanced BinPack"===e||"AZ Balanced BinPack Memory"===e?this.getAzBalancedMemoryBinPackStrategy():"BinPack"===e||"BinPack Memory"===e?this.getBinPackMemoryStrategy():"AZ Balanced BinPack CPU"===e?this.getAzBalancedCpuBinPackStrategy():"BinPack CPU"===e?this.getBinPackCpuStrategy():"One Task Per Host"===e?this.getOneTaskPerHostStrategy():[]}getAzBalancedSpreadStrategy(){return[{type:"spread",field:"attribute:ecs.availability-zone"},{type:"spread",field:"instanceId"}]}getAzBalancedMemoryBinPackStrategy(){return[{type:"spread",field:"attribute:ecs.availability-zone"},{type:"binpack",field:"memory"}]}getBinPackMemoryStrategy(){return[{type:"binpack",field:"memory"}]}getAzBalancedCpuBinPackStrategy(){return[{type:"spread",field:"attribute:ecs.availability-zone"},{type:"binpack",field:"cpu"}]}getBinPackCpuStrategy(){return[{type:"binpack",field:"cpu"}]}getOneTaskPerHostStrategy(){return[{type:"spread",field:"instanceId"}]}});const Ve="spinnaker.ecs.secret.read.service";t(Ve,[]).service("secretReader",class{listSecrets(){return r("/ecs/secrets").get()}});const _e="spinnaker.ecs.securityGroup.details.controller";e.module(_e,[V,S,k]).controller("ecsSecurityGroupDetailsCtrl",["$scope","$state","resolvedSecurityGroup","app","securityGroupReader",function(t,n,a,r,s){this.application=r;const o=r,c=a;function d(){return s.getSecurityGroupDetails(o,c.accountId,c.provider,c.region,c.vpcId,c.name).then(function(e){return de.getVpcName(e.vpcId).then(t=>(e.vpcName=t,e))}).then(function(n){if(t.state.loading=!1,!n||j.isEmpty(n))u();else{const a=s.getApplicationSecurityGroup(o,c.accountId,c.region,c.name);e.extend(c,a,n),t.securityGroup=c,t.ipRules=function(e){const t=j.groupBy(e.ipRangeRules,e=>e.range.ip+e.range.cidr);return Object.keys(t).map(e=>({address:e,rules:p(t,e)})).filter(e=>e.rules.length)}(c),t.securityGroupRules=function(e){const t=j.groupBy(e.securityGroupRules,e=>e.securityGroup.id);return Object.keys(t).map(e=>({securityGroup:t[e][0].securityGroup,rules:p(t,e)})).filter(e=>e.rules.length)}(c)}},u)}function p(e,t){const n=[];return e[t].forEach(e=>{(e.portRanges||[]).forEach(t=>{("-1"===e.protocol||void 0!==t.startPort&&void 0!==t.endPort)&&n.push({startPort:t.startPort,endPort:t.endPort,protocol:e.protocol})})}),n}function u(){t.$$destroyed||(r.isStandalone?(t.group=c.name,t.state.notFound=!0,t.state.loading=!1,l.removeLastItem("securityGroups")):n.go("^",{allowModalToStayOpen:!0},{location:"replace"}))}this.firewallLabel=C.get("Firewall"),t.detailsTemplateUrl=i.getValue("ecs","securityGroup.detailsTemplateUrl"),t.state={loading:!0,standalone:r.isStandalone},d().then(()=>{t.$$destroyed||r.isStandalone||r.securityGroups.onRefresh(t,d)}),r.isStandalone&&(r.securityGroups={refresh:d})}]);const je="spinnaker.ecs.securityGroup.reader";t(je,[]).service("ecsSecurityGroupReader",class{resolveIndexedSecurityGroup(e,t,n){return e[t.account][t.region][n]}});const We="spinnaker.ecs.securityGroup.transformer";t(We,[]).factory("ecsSecurityGroupTransformer",function(){return{normalizeSecurityGroup:function(){}}});const Ze="spinnaker.ecs.securityGroup";t(Ze,[je,We,_e]);class Ke{static listServiceDiscoveryRegistries(){return r("/ecs/serviceDiscoveryRegistries").get()}}class Je{constructor(e,t,n,a,r,i,s,o,l){this.$q=e,this.loadBalancerReader=t,this.serverGroupCommandRegistry=n,this.iamRoleReader=a,this.ecsClusterReader=r,this.metricAlarmReader=i,this.placementStrategyService=s,this.securityGroupReader=o,this.secretReader=l,this.launchTypes=["EC2","FARGATE"],this.networkModes=["bridge","host","awsvpc","none","default"]}configureUpdateCommand(e){e.backingData={launchTypes:Z(this.launchTypes),networkModes:Z(this.networkModes)}}configureCommand(e,t=""){this.applyOverrides("beforeConfiguration",e),e.toggleSuspendedProcess=(e,t)=>{e.suspendedProcesses=e.suspendedProcesses||[];const n=e.suspendedProcesses.indexOf(t);-1===n?e.suspendedProcesses.push(t):e.suspendedProcesses.splice(n,1)},e.processIsSuspended=(e,t)=>e.suspendedProcesses.includes(t),e.onStrategyChange=(e,t)=>{""!==t.key&&"custom"!==t.key&&(e.suspendedProcesses=(e.suspendedProcesses||[]).filter(e=>"AddToLoadBalancer"!==e))},e.regionIsDeprecated=e=>K(e,"backingData.filtered.regions")&&e.backingData.filtered.regions.some(t=>t.name===e.region&&t.deprecated);const n=e.imageDescription?[this.grabImageAndTag(e.imageDescription.imageId)]:[];let a;return t&&n.push(t),a=n.length?this.$q.all(n.map(e=>ve.findImages({provider:"dockerRegistry",count:50,q:e}))).then(e=>J(e)):this.$q.when([]),this.$q.all({credentialsKeyedByAccount:f.getCredentialsKeyedByAccount("ecs"),loadBalancers:this.loadBalancerReader.listLoadBalancers("ecs"),subnets:G.listSubnetsByProvider("ecs"),iamRoles:this.iamRoleReader.listRoles("ecs"),ecsClusters:this.ecsClusterReader.listClusters(),capacityProviderDetails:this.ecsClusterReader.describeClusters(e.credentials,e.region),metricAlarms:this.metricAlarmReader.listMetricAlarms(),securityGroups:this.securityGroupReader.getAllSecurityGroups(),launchTypes:this.$q.when(Z(this.launchTypes)),networkModes:this.$q.when(Z(this.networkModes)),secrets:this.secretReader.listSecrets(),serviceDiscoveryRegistries:Ke.listServiceDiscoveryRegistries(),images:a}).then(t=>{t.accounts=Y(t.credentialsKeyedByAccount),t.filtered={},e.viewState.contextImages&&(t.images=t.images.concat(e.viewState.contextImages)),e.backingData=t,this.configureVpcId(e),this.configureAvailableIamRoles(e),this.configureAvailableSubnetTypes(e),this.configureAvailableSecurityGroups(e),this.configureAvailableEcsClusters(e),this.setCapacityProviderDetails(e),this.configureAvailableSecrets(e),this.configureAvailableServiceDiscoveryRegistries(e),this.configureAvailableImages(e),this.configureAvailableRegions(e),this.configureLoadBalancerOptions(e),this.applyOverrides("afterConfiguration",e),this.attachEventHandlers(e)})}setCapacityProviderDetails(e){this.$q.all({capacityProviderDetails:this.ecsClusterReader.describeClusters(e.credentials,e.region)}).then(t=>{e.backingData.capacityProviderDetails=X(t.capacityProviderDetails).map(e=>this.mapCapacityProviderDetails(e)).value()}),null!=e.ecsClusterName&&e.ecsClusterName.length>0?this.configureAvailableCapacityProviders(e):(e.backingData.filtered.availableCapacityProviders=[],e.backingData.filtered.defaultCapacityProviderStrategy=[]),this.checkDirtyCapacityProviders(e)}configureAvailableCapacityProviders(e){e.backingData.filtered.availableCapacityProviders=X(e.backingData.capacityProviderDetails).filter({clusterName:e.ecsClusterName}).map(e=>e.capacityProviders).flattenDeep().value(),e.backingData.filtered.defaultCapacityProviderStrategy=X(e.backingData.capacityProviderDetails).filter({clusterName:e.ecsClusterName}).map(e=>e.defaultCapacityProviderStrategy).flattenDeep().value()}mapCapacityProviderDetails(e){return{capacityProviders:e.capacityProviders,clusterName:e.clusterName,defaultCapacityProviderStrategy:e.defaultCapacityProviderStrategy}}applyOverrides(e,t){this.serverGroupCommandRegistry.getCommandOverrides("ecs").forEach(n=>{n[e]&&n[e](t)})}grabImageAndTag(e){return e.split("/").pop()}buildImageId(e){return e.fromContext?`${e.imageLabelOrSha}`:e.fromTrigger&&!e.tag?`${e.registry}/${e.repository} (Tag resolved at runtime)`:`${e.registry}/${e.repository}:${e.tag}`}mapImage(e){return void 0!==e.message?e:{repository:e.repository,tag:e.tag,imageId:this.buildImageId(e),registry:e.registry,fromContext:e.fromContext,fromTrigger:e.fromTrigger,account:e.account,imageLabelOrSha:e.imageLabelOrSha,stageId:e.stageId,message:e.message}}configureAvailableImages(e){e.backingData.filtered.images=e.backingData.images.map(e=>this.mapImage(e))}configureAvailabilityZones(e){e.backingData.filtered.availabilityZones=Q(e.backingData.credentialsKeyedByAccount[e.credentials].regions,{name:e.region}).availabilityZones,e.availabilityZones=e.backingData.filtered.availabilityZones}configureAvailableSecurityGroups(e){if(null==e.subnetType&&(null==e.subnetTypes||0==e.subnetTypes.length))return void(e.backingData.filtered.securityGroups=[]);const t=X(e.backingData.subnets).filter({account:e.credentials,region:e.region,purpose:e.subnetTypes?e.subnetTypes[0]:e.subnetType}).compact().uniqBy("purpose").map("vpcId").value()[0];if(e.backingData.securityGroups[e.credentials]&&e.backingData.securityGroups[e.credentials].ecs&&e.backingData.securityGroups[e.credentials].ecs[e.region]){const n=e.backingData.securityGroups[e.credentials].ecs[e.region];e.backingData.filtered.securityGroupNames=X(n).filter({vpcId:t}).map("name").value()}}configureAvailableSubnetTypes(e){e.backingData.filtered.subnetTypes=X(e.backingData.subnets).filter({account:e.credentials,region:e.region}).compact().uniqBy("purpose").value().filter(function(e){return e.purpose&&e.purpose.length>0})}configureAvailableEcsClusters(e){e.backingData.filtered.ecsClusters=X(e.backingData.ecsClusters).filter({account:e.credentials,region:e.region}).map("name").value()}configureAvailableSecrets(e){e.backingData.filtered.secrets=X(e.backingData.secrets).filter({account:e.credentials,region:e.region}).map("name").value()}buildServiceRegistryDisplayName(e){return`${e.name} (${e.id})`}mapServiceRegistry(e){return{account:e.account,region:e.region,name:e.name,id:e.id,arn:e.arn,displayName:this.buildServiceRegistryDisplayName(e)}}configureAvailableServiceDiscoveryRegistries(e){e.backingData.filtered.serviceDiscoveryRegistries=X(e.backingData.serviceDiscoveryRegistries).filter({account:e.credentials,region:e.region}).map(e=>this.mapServiceRegistry(e)).value()}configureAvailableRegions(e){const t=e.backingData.credentialsKeyedByAccount[e.credentials]||{regions:[]};e.backingData.filtered.regions=t.regions}configureAvailableIamRoles(e){e.backingData.filtered.iamRoles=X(e.backingData.iamRoles).filter({accountName:e.credentials}).map("name").value(),e.backingData.filtered.iamRoles.length>0&&e.backingData.filtered.iamRoles.splice(0,0,"None (No IAM role)")}configureSubnetPurposes(e){const t={dirty:{}},n=e.backingData.filtered;return null===e.region||(n.subnetPurposes=X(e.backingData.subnets).filter({account:e.credentials,region:e.region}).reject({target:"elb"}).reject({purpose:null}).uniqBy("purpose").value(),e.subnetTypes?t.dirty.subnetType=!e.subnetTypes.every(e=>X(n.subnetPurposes).some({purpose:e}).value()):X(n.subnetPurposes).some({purpose:e.subnetType}).value()||(t.dirty.subnetType=!0),t.dirty.subnetType&&(e.subnetTypes=null,e.subnetType=null)),t}getLoadBalancerMap(e){return X(e.backingData.loadBalancers).map("accounts").flattenDeep().filter({name:e.credentials}).map("regions").flattenDeep().filter({name:e.region}).map("loadBalancers").flattenDeep().value()}getLoadBalancerNames(e){return this.getLoadBalancerMap(e).filter(t=>(!t.loadBalancerType||"classic"===t.loadBalancerType)&&t.vpcId===e.vpcId).map(e=>e.name).sort()}getVpcLoadBalancerNames(e){return this.getLoadBalancerMap(e).filter(e=>(!e.loadBalancerType||"classic"===e.loadBalancerType)&&e.vpcId).map(e=>e.name).sort()}getTargetGroupNames(e){const t=this.getLoadBalancerMap(e).filter(e=>"classic"!==e.loadBalancerType);return J(t.map(e=>e.targetGroups)).sort()}configureLoadBalancerOptions(e){const t={dirty:{}},n=(e.loadBalancers||[]).concat(e.vpcLoadBalancers||[]),a=this.getLoadBalancerNames(e),r=this.getVpcLoadBalancerNames(e),i=this.getTargetGroupNames(e),s=e.targetGroupMappings.map(e=>e.targetGroup);if(n&&e.loadBalancers){const i=e.vpcId?a:a.concat(r),s=ee(i,n),o=te(s,n);e.loadBalancers=ee(a,s),e.vpcId?delete e.vpcLoadBalancers:e.vpcLoadBalancers=ee(r,s),o.length&&(t.dirty.loadBalancers=o)}if(s){const t=ee(i,s),n=te(t,s);n&&n.length>0?e.viewState.dirty.targetGroups=n:e.viewState.dirty&&e.viewState.dirty.targetGroups&&(e.viewState.dirty.targetGroups=[])}return e.backingData.filtered.loadBalancers=a,e.backingData.filtered.vpcLoadBalancers=r,e.backingData.filtered.targetGroups=i,t}refreshLoadBalancers(e,t){return this.loadBalancerReader.listLoadBalancers("ecs").then(n=>{e.backingData.loadBalancers=n,t||this.configureLoadBalancerOptions(e)})}configureVpcId(e){const t={dirty:{}};if(null!=e.subnetType||null!=e.subnetTypes&&0!=e.subnetTypes.length)if(null!=e.subnetTypes&&e.subnetTypes.length>0)e.subnetTypes.forEach(function(t){const n=Q(e.backingData.subnets,{purpose:t,account:e.credentials,region:e.region});e.vpcId=n?n.vpcId:null});else{const t=Q(e.backingData.subnets,{purpose:e.subnetType,account:e.credentials,region:e.region});e.vpcId=t?t.vpcId:null}else e.vpcId=null,t.dirty.vpcId=!0;return t}checkDirtyCapacityProviders(e){if(e.capacityProviderStrategy){const t=e.backingData.filtered.availableCapacityProviders,n=e.capacityProviderStrategy.map(e=>e.capacityProvider),a=ee(t,n),r=te(a,n);if(r&&r.length>0?e.viewState.dirty.customCapacityProviders=r:e.viewState.dirty&&e.viewState.dirty.customCapacityProviders&&(e.viewState.dirty.customCapacityProviders=[]),e.useDefaultCapacityProviders){const t=e.backingData.filtered.defaultCapacityProviderStrategy.map(e=>e.capacityProvider),a=ee(t,n),r=te(a,n);r&&r.length>0&&(e.viewState.dirty.defaulCapacityProviders=r)}}}attachEventHandlers(e){e.subnetChanged=e=>{const t=this.configureVpcId(e);return ne(t.dirty,this.configureLoadBalancerOptions(e).dirty),e.viewState.dirty=e.viewState.dirty||{},ne(e.viewState.dirty,t.dirty),t},e.regionChanged=e=>{const t={dirty:{}};return ne(t.dirty,this.configureSubnetPurposes(e).dirty),e.region&&(ne(t.dirty,e.subnetChanged(e).dirty),this.configureAvailabilityZones(e),this.configureAvailableEcsClusters(e),this.configureAvailableSubnetTypes(e),this.configureAvailableSecurityGroups(e),this.configureAvailableSecrets(e),this.configureAvailableServiceDiscoveryRegistries(e),this.setCapacityProviderDetails(e)),t},e.subnetTypeChanged=e=>(this.configureAvailableSecurityGroups(e),{dirty:{}}),e.clusterChanged=e=>{e.moniker=A.getMoniker(e.application,e.stack,e.freeFormDetails)},e.credentialsChanged=e=>{const t={dirty:{}},n=e.backingData;return e.credentials?(this.configureAvailableIamRoles(e),this.configureAvailableEcsClusters(e),this.configureAvailableSubnetTypes(e),this.configureAvailableSecurityGroups(e),this.configureAvailableSecrets(e),this.configureAvailableServiceDiscoveryRegistries(e),this.configureAvailableRegions(e),this.setCapacityProviderDetails(e),ae(n.filtered.regions,{name:e.region})?ne(t.dirty,e.regionChanged(e).dirty):(e.region=null,t.dirty.region=!0)):e.region=null,t},e.placementStrategyNameChanged=e=>(e.placementStrategySequence=this.placementStrategyService.getPredefinedStrategy(e.placementStrategyName),{dirty:{}}),this.applyOverrides("attachEventHandlers",e)}}Je.$inject=["$q","loadBalancerReader","serverGroupCommandRegistry","iamRoleReader","ecsClusterReader","metricAlarmReader","placementStrategyService","securityGroupReader","secretReader"];const Ye="spinnaker.ecs.serverGroup.configure.service";t(Ye,[w,S,E,D]).service("ecsServerGroupConfigurationService",Je);const Xe="spinnaker.ecs.serverGroupCommandBuilder.service";e.module(Xe,[T,Ye]).factory("ecsServerGroupCommandBuilder",["$q","instanceTypeService","ecsServerGroupConfigurationService",function(t,n,a){function r(e,t,n={}){if(n[e.refId])return[];n[e.refId]=!0;let a=[];return"findImageFromTags"===e.type&&a.push({fromContext:!0,imageLabelOrSha:e.imageLabelOrSha,stageId:e.refId}),e.requisiteStageRefIds.forEach(function(e){const i=t.find(t=>t.refId===e);i&&(a=a.concat(r(i,t,n)))}),a}function i(e){return e.filter(e=>"docker"===e.type).map(e=>({fromTrigger:!0,repository:e.repository,account:e.account,organization:e.organization,registry:e.registry,tag:e.tag}))}function s(e,n){n=n||{};const a=f.getCredentialsKeyedByAccount("ecs"),r=n.account||e.defaultCredentials.ecs,i=n.region||e.defaultRegions.ecs,s=f.getAvailabilityZonesForAccountAndRegion("ecs",r,i);return t.all({preferredZones:s,credentialsKeyedByAccount:a}).then(function(t){const a=t.preferredZones;let s="None (No IAM role)";s=s.replace("{{application}}",e.name);const o={application:e.name,credentials:r,region:i,strategy:"",capacity:{min:1,max:1,desired:1},launchType:"EC2",healthCheckType:"EC2",selectedProvider:"ecs",iamRole:s,dockerImageCredentialsSecret:"None (No registry credentials)",availabilityZones:a,subnetType:"",securityGroupNames:[],healthCheckGracePeriodSeconds:"",placementConstraints:[],placementStrategyName:"",taskDefinitionArtifact:{},useTaskDefinitionArtifact:!1,placementStrategySequence:[],serviceDiscoveryAssociations:[],ecsClusterName:"",targetGroup:"",copySourceScalingPoliciesAndActions:!0,preferSourceCapacity:!0,useSourceCapacity:!0,enableDeploymentCircuitBreaker:!1,viewState:{useAllImageSelection:!1,useSimpleCapacity:!0,usePreferredZones:!0,mode:n.mode||"create",disableStrategySelection:!0,dirty:{}}};return e.attributes&&e.attributes.platformHealthOnlyShowOverride&&e.attributes.platformHealthOnly&&(o.interestingHealthProviderNames=["ecs"]),o})}return{buildNewServerGroupCommand:s,buildServerGroupCommandFromExisting:function(e,t,n="clone"){return s(e,{account:t.account,region:t.region}).then(function(e){return e.credentials=t.account,e.app=t.moniker.app,e.stack=t.moniker.stack,e.region=t.region,e.ecsClusterName=t.ecsCluster,e.capacity=t.capacity,e.viewState.mode=n,e})},buildNewServerGroupCommandForPipeline:function(e,n){let a=r(e,n.stages)||[];return a=a.concat(i(n.triggers)),t.when({viewState:{requiresTemplateSelection:!0,overrides:{viewState:{mode:"editPipeline",contextImages:a,pipeline:n,currentStage:e}}}})},buildServerGroupCommandFromPipeline:function(t,n,a,o){const l=j.cloneDeep(n),c=Object.keys(l.availabilityZones)[0];return s(t,{account:l.account,region:c}).then(function(t){const n=l.availabilityZones[c].join(",")===t.availabilityZones.join(",");let s=r(a,o.stages)||[];s=s.concat(i(o.triggers)),t.docker&&t.docker.image&&(t.docker.image=function(e,t){if(e.fromContext){const n=t.find(t=>e.stageId===t.stageId);return n?(e.cluster=n.cluster,e.pattern=n.pattern,e.repository=n.repository,e):null}if(e.fromTrigger)return t.find(t=>e.registry===t.registry&&e.repository===t.repository&&e.tag===t.tag)?e:null;return e}(t.docker.image,s));const d={instanceProfile:void 0,disableImageSelection:!0,useSimpleCapacity:l.capacity.min===l.capacity.max&&!0!==l.useSourceCapacity,usePreferredZones:n,mode:"editPipeline",submitButtonLabel:"Done",templatingEnabled:!0,existingPipelineCluster:!0,dirty:{},contextImages:s,pipeline:o,currentStage:a},p={region:c,credentials:l.account,availabilityZones:l.availabilityZones[c],viewState:d};return l.strategy=l.strategy||"",e.extend({},t,l,p)})},buildUpdateServerGroupCommand:function(e){const t={type:"modifyAsg",asgs:[{asgName:e.name,region:e.region}],healthCheckType:e.asg.healthCheckType,credentials:e.account};return a.configureUpdateCommand(t),t}}}]);const Qe="spinnaker.ecs.cloneServerGroup.controller";t(Qe,[V,Ye,N,P,D,De,Ee,Ve,I]).controller("ecsCloneServerGroupCtrl",["$scope","$uibModalInstance","$q","$state","serverGroupWriter","overrideRegistry","ecsServerGroupConfigurationService","serverGroupCommandRegistry","serverGroupCommand","iamRoleReader","ecsClusterReader","secretReader","application","title",function(e,t,n,a,r,i,s,o,l,c,d,p,u,m){function g(){if(e.$$destroyed)return;const t=e.taskMonitor.task.execution.stages.find(e=>"cloneServerGroup"===e.type);if(t&&t.context["deploy.server.groups"]){const n=t.context["deploy.server.groups"][e.command.region];if(n){const t={serverGroup:n,accountId:e.command.credentials,region:e.command.region,provider:"ecs"};let r="^.^.^.clusters.serverGroup";a.includes("**.clusters.serverGroup")&&(r="^.serverGroup"),a.includes("**.clusters.cluster.serverGroup")&&(r="^.^.serverGroup"),a.includes("**.clusters")&&(r=".serverGroup"),a.go(r,t)}}}function v(){s.configureCommand(e.command).then(function(){e.state.loaded=!0,e.command.credentialsChanged(l),e.command.regionChanged(l),e.$watch("command.subnetType",h(e.command.subnetTypeChanged)),e.$watch("command.credentials",h(e.command.credentialsChanged)),e.$watch("command.region",h(e.command.regionChanged)),e.$watch("command.placementStrategyName",h(e.command.placementStrategyNameChanged)),e.$watch("command.stack",()=>e.command.clusterChanged(e.command)),e.$watch("command.freeFormDetails",()=>e.command.clusterChanged(e.command))})}function h(e){return function(){e(l)}}e.pages={templateSelection:i.getTemplate("ecs.serverGroup.templateSelection","ecs/src/serverGroup/configure/wizard/templateSelection/templateSelection.html"),basicSettings:i.getTemplate("ecs.serverGroup.basicSettings","ecs/src/serverGroup/configure/wizard/location/basicSettings.html"),container:i.getTemplate("ecs.serverGroup.container","ecs/src/serverGroup/configure/wizard/container/container.html"),horizontalScaling:i.getTemplate("ecs.serverGroup.horizontalScaling","ecs/src/serverGroup/configure/wizard/horizontalScaling/horizontalScaling.html"),networking:i.getTemplate("ecs.serverGroup.networking","ecs/src/serverGroup/configure/wizard/networking/networking.html"),logging:i.getTemplate("ecs.serverGroup.logging","ecs/src/serverGroup/configure/wizard/logging/logging.html"),serviceDiscovery:i.getTemplate("ecs.serverGroup.serviceDiscovery","ecs/src/serverGroup/configure/wizard/serviceDiscovery/serviceDiscovery.html"),advancedSettings:i.getTemplate("ecs.serverGroup.advancedSettings","ecs/src/serverGroup/configure/wizard/advancedSettings/advancedSettings.html"),taskDefinition:i.getTemplate("ecs.taskDefinition","ecs/src/serverGroup/configure/wizard/taskDefinition/taskDefinition.html")},e.title=m,e.applicationName=u.name,e.application=u,e.command=l,e.state={loaded:!1,requiresTemplateSelection:!!l.viewState.requiresTemplateSelection},this.templateSelectionText={copied:["account, region, ecs cluster, stack","capacity"],notCopied:["launch type, target group, network mode"]},e.command.viewState.disableStrategySelection||this.templateSelectionText.notCopied.push("the deployment strategy (if any) used to deploy the most recent server group"),e.taskMonitor=new z({application:u,title:"Creating your server group",modalInstance:t,onTaskComplete:function(){u.serverGroups.refresh(),u.serverGroups.onNextRefresh(e,g)}}),this.isValid=function(){return!0},this.showSubmitButton=function(){return x.allPagesVisited()},this.submit=function(){if("editPipeline"===e.command.viewState.mode||"createPipeline"===e.command.viewState.mode)return t.close(e.command);e.taskMonitor.submit(function(){return r.cloneServerGroup(e.command,u)})},this.cancel=function(){t.dismiss()},e.state.requiresTemplateSelection?e.state.loaded=!0:v(),this.templateSelected=()=>{e.state.requiresTemplateSelection=!1,v()},e.notifyAngular=function(t,n){"pipeline"==t?e.command.viewState.pipeline=n:e.command[t]=n},e.configureCommand=function(t){return s.configureCommand(e.command,t)},e.capacityProviderState={useCapacityProviders:e.command.capacityProviderStrategy&&e.command.capacityProviderStrategy.length>0,updateComputeOption:function(t){"launchType"==t?e.command.capacityProviderStrategy=[]:"capacityProviders"==t&&(e.command.launchType="",e.command.capacityProviderStrategy=e.command.capacityProviderStrategy||[])}}}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/serverGroup/configure/wizard/templateSelection/templateSelection.html",'<deploy-initializer\n cloud-provider="ecs"\n command="command"\n application="application"\n parent-state="state"\n dismiss="ctrl.cancel()"\n template-selection-text="ctrl.templateSelectionText"\n on-template-selected="ctrl.templateSelected()"\n></deploy-initializer>\n')}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/serverGroup/configure/wizard/location/basicSettings.html",'<div class="container-fluid form-horizontal" ng-controller="ecsServerGroupBasicSettingsCtrl as basicSettingsCtrl">\n <ng-form name="basicSettings">\n <div class="form-group row" ng-if="command.regionIsDeprecated(command)">\n <div class="col-md-12 error-message">\n <div class="alert alert-danger">\n You are deploying into a deprecated region within the {{ command.credentials }} account!\n </div>\n </div>\n </div>\n <div class="form-group">\n <div class="col-md-3 sm-label-right">Account</div>\n <div class="col-md-7">\n <account-select-field\n read-only="command.viewState.readOnlyFields.credentials"\n component="command"\n field="credentials"\n accounts="command.backingData.accounts"\n provider="\'ecs\'"\n ></account-select-field>\n </div>\n </div>\n <region-select-field\n read-only="command.viewState.readOnlyFields.region"\n label-columns="3"\n component="command"\n field="region"\n account="command.credentials"\n provider="\'ecs\'"\n regions="command.backingData.filtered.regions"\n ></region-select-field>\n <div class="form-group">\n <div class="col-md-3 sm-label-right">\n ECS Cluster name <help-field key="ecs.serverGroup.clusterName"></help-field>\n </div>\n <div class="col-md-7">\n <div class="form-control-static" ng-if="!command.backingData.filtered.ecsClusters.length">\n No ECS clusters found in the selected account/region\n </div>\n <ui-select\n data-test-id="ServerGroup.clusterName"\n ng-model="command.ecsClusterName"\n ng-if="command.backingData.filtered.ecsClusters.length"\n class="form-control input-sm"\n required\n on-select="fieldChanged()"\n >\n <ui-select-match>{{$select.selected}}</ui-select-match>\n <ui-select-choices\n repeat="ecsClusterName in command.backingData.filtered.ecsClusters | filter: $select.search"\n >\n <span ng-bind-html="ecsClusterName"></span>\n </ui-select-choices>\n </ui-select>\n </div>\n </div>\n <div class="form-group">\n <div class="col-md-3 sm-label-right">\n Stack\n <help-field key="ecs.serverGroup.stack"></help-field>\n </div>\n <div class="col-md-7">\n <input\n data-test-id="ServerGroup.stack"\n type="text"\n class="form-control input-sm no-spel"\n ng-pattern="basicSettingsCtrl.stackPattern"\n name="stack"\n ng-model="command.stack"\n />\n </div>\n </div>\n <div class="form-group row slide-in" ng-if="basicSettings.stack.$error.pattern">\n <div class="col-sm-9 col-sm-offset-2 error-message">\n <span>Only dot(.) and underscore(_) special characters are allowed in the Stack field.</span>\n </div>\n </div>\n <div class="form-group">\n <div class="col-md-3 sm-label-right">\n Detail\n <help-field key="ecs.serverGroup.detail"></help-field>\n </div>\n <div class="col-md-7">\n <input\n data-test-id="ServerGroup.details"\n type="text"\n class="form-control input-sm no-spel"\n ng-pattern="basicSettingsCtrl.detailPattern"\n name="details"\n ng-model="command.freeFormDetails"\n />\n </div>\n </div>\n <div class="form-group row slide-in" ng-if="basicSettings.details.$error.pattern">\n <div class="col-sm-9 col-sm-offset-2 error-message">\n <span>Only dot(.), underscore(_), and dash(-) special characters are allowed in the Detail field.</span>\n </div>\n </div>\n <deployment-strategy-selector\n ng-if="!command.viewState.disableStrategySelection && command.selectedProvider"\n command="command"\n ></deployment-strategy-selector>\n <div class="form-group" ng-if="!command.viewState.hideClusterNamePreview">\n <div class="col-md-12">\n <div class="well-compact" ng-class="basicSettingsCtrl.showPreviewAsWarning() ? \'alert alert-warning\' : \'well\'">\n <h5 class="text-center">\n <p>Your server group will be in the cluster:</p>\n <p>\n <strong>\n {{basicSettingsCtrl.getNamePreview()}}\n <span ng-if="basicSettingsCtrl.createsNewCluster()"> (new cluster)</span>\n </strong>\n </p>\n <div\n class="text-left"\n ng-if="!basicSettingsCtrl.createsNewCluster() && command.viewState.mode === \'create\' && latestServerGroup"\n >\n <p>There is already a server group in this cluster. Do you want to clone it?</p>\n <p>\n Cloning copies the entire configuration from the selected server group, allowing you to modify whichever\n fields (e.g. image) you need to change in the new server group.\n </p>\n <p>\n To clone a server group, select "Clone" from the "Server Group Actions" menu in the details view of the\n server group.\n </p>\n <p>\n <a href ng-click="basicSettingsCtrl.navigateToLatestServerGroup()">\n Go to details for {{latestServerGroup.name}}\n </a>\n </p>\n </div>\n </h5>\n </div>\n </div>\n </div>\n </ng-form>\n</div>\n')}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/serverGroup/configure/wizard/container/container.html",'<div class="clearfix">\n <div class="col-md-12">\n <container-react\n command="command"\n notify-angular="notifyAngular"\n configure-command="configureCommand"\n ></container-react>\n </div>\n</div>\n')}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/serverGroup/configure/wizard/horizontalScaling/horizontalScaling.html",'<div class="clearfix">\n <div class="row">\n <div class="col-md-12">\n <ecs-server-group-horizontal-scaling\n command="command"\n application="application"\n capacity-provider-state="capacityProviderState"\n notify-angular="notifyAngular"\n configure-command="configureCommand"\n ></ecs-server-group-horizontal-scaling>\n </div>\n </div>\n</div>\n')}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/serverGroup/configure/wizard/networking/networking.html",'<div class="clearfix">\n <div class="col-md-12">\n <ecs-networking-react\n command="command"\n notify-angular="notifyAngular"\n configure-command="configureCommand"\n ></ecs-networking-react>\n </div>\n</div>\n')}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/serverGroup/configure/wizard/logging/logging.html",'<div class="clearfix">\n <div class="row">\n <div class="col-md-12">\n <ecs-server-group-logging command="command" application="application"></ecs-server-group-logging>\n </div>\n </div>\n</div>\n')}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/serverGroup/configure/wizard/serviceDiscovery/serviceDiscovery.html",'<div class="clearfix">\n <div class="row">\n <div class="col-md-12">\n <service-discovery-react\n command="command"\n notify-angular="notifyAngular"\n configure-command="configureCommand"\n ></service-discovery-react>\n </div>\n </div>\n</div>\n')}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/serverGroup/configure/wizard/advancedSettings/advancedSettings.html",'<div class="clearfix">\n <div class="row">\n <div class="col-md-12">\n <ecs-server-group-advanced-settings\n command="command"\n application="application"\n ></ecs-server-group-advanced-settings>\n </div>\n </div>\n</div>\n')}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/serverGroup/configure/wizard/taskDefinition/taskDefinition.html",'<div class="clearfix">\n <div class="row">\n <div class="col-md-12">\n <div class="container-fluid form-horizontal">\n <div class="form-group">\n <div class="col-md-4 sm-label-right">\n <b>Task Definition source</b>\n <help-field key="ecs.taskDefinition"></help-field>\n </div>\n <div class="col-md-2 radio">\n <label>\n <input\n data-test-id="ServerGroup.useInputs"\n type="radio"\n ng-model="command.useTaskDefinitionArtifact"\n ng-value="false"\n id="taskDefinitionSourceInputs"\n />\n Inputs\n </label>\n </div>\n <div class="col-md-1 radio">\n <label>\n <input\n data-test-id="ServerGroup.useArtifacts"\n type="radio"\n ng-model="command.useTaskDefinitionArtifact"\n ng-value="true"\n ng-disabled="command.viewState.mode === \'create\'"\n id="taskDefinitionSourceArtifact"\n />\n Artifact\n </label>\n </div>\n </div>\n <div ng-if="command.viewState.mode === \'create\'" class="color-text-caption">\n <hr />\n <span><em>Artifacts not supported outside of pipelines.</em></span>\n </div>\n </div>\n </div>\n <div class="col-md-12" ng-if="command.useTaskDefinitionArtifact">\n <hr />\n <task-definition-react\n command="command"\n notify-angular="notifyAngular"\n configure-command="configureCommand"\n ></task-definition-react>\n </div>\n </div>\n</div>\n')}]);const et="spinnaker.ecs.serverGroup.configure.wizard.advancedSettings.component";t(et,[]).component("ecsServerGroupAdvancedSettings",{bindings:{command:"=",application:"="},templateUrl:"ecs/src/serverGroup/configure/wizard/advancedSettings/advancedSettings.component.html"}),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/serverGroup/configure/wizard/advancedSettings/advancedSettings.component.html",'<div class="container-fluid form-horizontal">\n <div class="form-group">\n <div class="col-md-5 sm-label-right">\n Health Check Grace Period\n <help-field key="ecs.healthgraceperiod"></help-field>\n </div>\n <div class="col-md-2">\n <input\n type="number"\n class="form-control input-sm no-spel"\n ng-model="$ctrl.command.healthCheckGracePeriodSeconds"\n />\n </div>\n </div>\n\n <div class="form-group">\n <div class="col-md-5 sm-label-right">\n <b>ECS IAM Instance Profile</b> <help-field key="ecs.iamrole"></help-field>\n </div>\n \x3c!-- TODO - Add a help box that explains that the container does not share profiles with the host --\x3e\n\n <div class="col-md-7" ng-if="!$ctrl.command.backingData.filtered.iamRoles.length">\n No account was selected, or no IAM roles are available for ECS tasks in this account.\n </div>\n\n <div class="col-md-7" ng-if="$ctrl.command.backingData.filtered.iamRoles.length">\n <ui-select\n ng-model="$ctrl.command.iamRole"\n class="form-control input-sm"\n required\n on-select="$ctrl.fieldChanged()"\n >\n <ui-select-match>{{ $select.selected }}</ui-select-match>\n <ui-select-choices repeat="iamRole in $ctrl.command.backingData.filtered.iamRoles | filter: $select.search">\n <span ng-bind-html="iamRole"></span>\n </ui-select-choices>\n </ui-select>\n </div>\n </div>\n\n <div ng-if="!$ctrl.command.useTaskDefinitionArtifact">\n <div class="form-group">\n <div class="col-md-5 sm-label-right">\n <b>Docker Image Credentials</b> <help-field key="ecs.dockerimagecredentials"></help-field>\n </div>\n <div class="col-md-7" ng-if="!$ctrl.command.backingData.filtered.secrets.length">\n No account or region was selected, or no AWS Secrets Manager secrets are available in this account and region.\n </div>\n\n <div class="col-md-7" ng-if="$ctrl.command.backingData.filtered.secrets.length">\n <ui-select\n ng-model="$ctrl.command.dockerImageCredentialsSecret"\n class="form-control input-sm"\n required\n on-select="$ctrl.fieldChanged()"\n >\n <ui-select-match>{{ $select.selected }}</ui-select-match>\n <ui-select-choices repeat="secret in $ctrl.command.backingData.filtered.secrets | filter: $select.search">\n <span ng-bind-html="secret"></span>\n </ui-select-choices>\n </ui-select>\n </div>\n </div>\n </div>\n\n <div class="form-group">\n <div class="col-md-5 sm-label-right">\n Fargate platform version\n <help-field key="ecs.platformVersion"></help-field>\n </div>\n <div class="col-md-3">\n <input\n type="text"\n class="form-control input-sm"\n name="platformVersion"\n ng-model="$ctrl.command.platformVersion"\n />\n </div>\n </div>\n\n <div class="form-group">\n <div class="col-md-5 sm-label-right">\n Enable Deployment Circuit Breaker\n <help-field key="ecs.enableDeploymentCircuitBreaker"></help-field>\n </div>\n <div class="col-md-3">\n <input type="checkbox" ng-model="$ctrl.command.enableDeploymentCircuitBreaker" />\n </div>\n </div>\n\n <div class="form-group">\n <div class="col-md-5 sm-label-right">\n <b>Placement Strategy</b> <help-field key="ecs.placementStrategy"></help-field>\n </div>\n <div class="col-md-7">\n <ui-select ng-model="$ctrl.command.placementStrategyName" class="form-control input-sm">\n <ui-select-match>{{ $select.selected }}</ui-select-match>\n <ui-select-choices\n repeat="item in [\'AZ Balanced Spread\', \'AZ Balanced BinPack CPU\', \'AZ Balanced BinPack Memory\', \'BinPack CPU\', \'BinPack Memory\', \'One Task Per Host\', \'None\'] | filter: $select.search"\n >\n <span ng-bind-html="item"></span>\n </ui-select-choices>\n </ui-select>\n \x3c!-- TODO - implement handling of custom placement strategies and constraints --\x3e\n </div>\n </div>\n\n <div class="form-group">\n <div class="sm-label-left">\n <b>Placement Constraints</b>\n <help-field key="ecs.placementConstraints"></help-field>\n </div>\n <form name="ecsPlacementConstraints">\n <table class="table table-condensed packed tags">\n <thead>\n <tr>\n <th style="width: 25%">Type <help-field key="ecs.placementConstraintType"></help-field></th>\n <th style="width: 68%">Expression <help-field key="ecs.placementConstraintExpression"></help-field></th>\n <th></th>\n </tr>\n </thead>\n <tbody>\n <tr ng-repeat="constraint in $ctrl.command.placementConstraints">\n <td>\n <select\n class="form-control input-sm"\n ng-model="constraint.type"\n ng-options="type for type in [\'distinctInstance\', \'memberOf\']"\n ></select>\n </td>\n <td>\n <input type="text" class="form-control input-sm no-spel" ng-model="constraint.expression" />\n </td>\n <td>\n <div class="form-control-static">\n <a class="btn-link sm-label" ng-click="$ctrl.command.placementConstraints.splice($index, 1)">\n <span class="glyphicon glyphicon-trash"></span>\n <span class="sr-only">Remove</span>\n </a>\n </div>\n </td>\n </tr>\n </tbody>\n <tfoot>\n <tr>\n <td colspan="3">\n <button class="btn btn-block btn-sm add-new" ng-click="$ctrl.command.placementConstraints.push({})">\n <span class="glyphicon glyphicon-plus-sign"></span>\n Add New Placement Constraint\n </button>\n </td>\n </tr>\n </tfoot>\n </table>\n </form>\n </div>\n\n <div ng-if="!$ctrl.command.useTaskDefinitionArtifact">\n <div class="form-group">\n <div class="sm-label-left">\n <b>Docker labels (optional)</b>\n <help-field key="ecs.dockerLabels"></help-field>\n </div>\n <map-editor model="$ctrl.command.dockerLabels" allow-empty="true"></map-editor>\n </div>\n\n <div class="form-group">\n <div class="sm-label-left">\n <b>Environment Variables (optional)</b>\n <help-field key="ecs.environmentVariables"></help-field>\n </div>\n <map-editor model="$ctrl.command.environmentVariables" allow-empty="true"></map-editor>\n </div>\n </div>\n\n <div class="form-group">\n <div class="sm-label-left">\n <b>Tags (optional)</b>\n <help-field key="ecs.tags"></help-field>\n </div>\n <map-editor model="$ctrl.command.tags" allow-empty="true"></map-editor>\n </div>\n\n <div ng-if="$ctrl.command.useTaskDefinitionArtifact" style="color: #666">\n <hr />\n <p>\n <em\n ><strong>Docker Image Credentials, Docker labels</strong>, and <strong>Environment Variables</strong> cannot be\n individually set when using a Task Definition artifact. Please include them in their respective container\n definition in that file.\n </em>\n </p>\n </div>\n</div>\n')}]);class tt extends ue.Component{constructor(e){super(e),this.getAvailableCapacityProviders=e=>e.backingData&&e.backingData.filtered&&e.backingData.filtered.availableCapacityProviders?e.backingData.filtered.availableCapacityProviders:[],this.getDefaultCapacityProviderStrategy=e=>e.backingData&&e.backingData.filtered&&e.backingData.filtered.defaultCapacityProviderStrategy?e.backingData.filtered.defaultCapacityProviderStrategy:[],this.getCapacityProviderStrategy=(e,t)=>e&&t.backingData&&t.backingData.filtered&&t.backingData.filtered.defaultCapacityProviderStrategy?t.backingData.filtered.defaultCapacityProviderStrategy:this.state.capacityProviderStrategy,this.addCapacityProviderStrategy=()=>{const e=this.state.capacityProviderStrategy;e.push({capacityProvider:"",base:null,weight:null}),this.props.notifyAngular("capacityProviderStrategy",e),this.setState({capacityProviderStrategy:e})},this.removeCapacityProviderStrategy=e=>{const t=this.state.capacityProviderStrategy;t.splice(e,1),this.props.notifyAngular("capacityProviderStrategy",t),this.setState({capacityProviderStrategy:t})},this.updateCapacityProviderName=(e,t)=>{const n=this.state.capacityProviderStrategy;n[e].capacityProvider=t,this.props.notifyAngular("capacityProviderStrategy",n),this.setState({capacityProviderStrategy:n}),this.props.command.viewState.dirty.customCapacityProviders=[]},this.updateCapacityProviderBase=(e,t)=>{const n=this.state.capacityProviderStrategy;n[e].base=t,this.props.notifyAngular("capacityProviderStrategy",n),this.setState({capacityProviderStrategy:n})},this.updateCapacityProviderWeight=(e,t)=>{const n=this.state.capacityProviderStrategy;n[e].weight=t,this.props.notifyAngular("capacityProviderStrategy",n),this.setState({capacityProviderStrategy:n})},this.updateCapacityProviderType=e=>{this.setState({useDefaultCapacityProviders:e}),this.props.notifyAngular("useDefaultCapacityProviders",e),this.props.command.viewState.dirty.customCapacityProviders=[];const t=e&&this.state.defaultCapacityProviderStrategy.length>0?this.state.defaultCapacityProviderStrategy:[];this.setState({capacityProviderStrategy:t}),this.props.notifyAngular("capacityProviderStrategy",t)};const t=this.props.command;this.state={availableCapacityProviders:this.getAvailableCapacityProviders(t),defaultCapacityProviderStrategy:this.getDefaultCapacityProviderStrategy(t),ecsClusterName:t.ecsClusterName,useDefaultCapacityProviders:t.useDefaultCapacityProviders||t.capacityProviderStrategy&&0==t.capacityProviderStrategy.length,capacityProviderStrategy:t.capacityProviderStrategy&&t.capacityProviderStrategy.length>0?t.capacityProviderStrategy:[],capacityProviderLoadedFlag:!1}}componentDidMount(){this.props.configureCommand("1").then(()=>{const e=this.props.command,t=this.state.useDefaultCapacityProviders;this.setState({availableCapacityProviders:this.getAvailableCapacityProviders(e),defaultCapacityProviderStrategy:this.getDefaultCapacityProviderStrategy(e),capacityProviderStrategy:this.getCapacityProviderStrategy(t,e),capacityProviderLoadedFlag:!0}),this.props.notifyAngular("useDefaultCapacityProviders",this.state.useDefaultCapacityProviders),this.props.notifyAngular("capacityProviderStrategy",this.state.capacityProviderStrategy)})}render(){const e=this.updateCapacityProviderName,t=this.updateCapacityProviderBase,n=this.updateCapacityProviderWeight,a=this.addCapacityProviderStrategy,r=this.removeCapacityProviderStrategy,i=this.updateCapacityProviderType,s=this.state.capacityProviderStrategy,o=this.state.useDefaultCapacityProviders,l=this.state.capacityProviderLoadedFlag,c=this.props.command.viewState.dirty&&this.props.command.viewState.dirty.customCapacityProviders?this.props.command.viewState.dirty.customCapacityProviders:[],d=this.props.command.viewState.dirty&&this.props.command.viewState.dirty.defaulCapacityProviders?this.props.command.viewState.dirty.defaulCapacityProviders:[],p=this.state.availableCapacityProviders&&this.state.availableCapacityProviders.length>0?this.state.availableCapacityProviders.map(e=>({label:`${e}`,value:e})):[],u=o&&d?ue.createElement("div",{className:"alert alert-warning"},ue.createElement("p",{className:"text-left"},ue.createElement("i",{className:"fa fa-exclamation-triangle"}),"Invalid capacity providers are a part of default capacity provider strategy.",ue.createElement("br",null),"Please click 'Done' to use current default capacity provider strategy (shown below) or switch to using a custom strategy.")):"",m=c?c.map(function(e,t){return ue.createElement("li",{key:t},e)}):"",g=o&&d.length>0?u:c.length>0&&!o?ue.createElement("div",{className:"alert alert-warning"},ue.createElement("p",null,ue.createElement("i",{className:"fa fa-exclamation-triangle"}),"The following capacity providers could not be found in the selected account/region/cluster and were removed:"),ue.createElement("ul",null,m),ue.createElement("br",null),ue.createElement("p",{className:"text-left"},"Please select the capacity provider(s) from the dropdown to resolve this error.")):"",v=s.length>0?s.map(function(a,i){return ue.createElement("tr",{key:i},o?ue.createElement("td",null,ue.createElement("input",{"data-test-id":"ServerGroup.defaultCapacityProvider.name."+i,type:"string",className:"form-control input-sm no-spel",required:!0,value:a.capacityProvider,disabled:!0})):ue.createElement("td",{"data-test-id":"ServerGroup.customCapacityProvider.name."+i},ue.createElement(M,{placeholder:"Select capacity provider",options:p,value:a.capacityProvider,onChange:t=>{e(i,t.label)},clearable:!1})),ue.createElement("td",null,ue.createElement("input",{"data-test-id":"ServerGroup.capacityProvider.base."+i,disabled:o,type:"number",className:"form-control input-sm no-spel",value:a.base,onChange:e=>t(i,e.target.valueAsNumber)})),ue.createElement("td",null,ue.createElement("input",{"data-test-id":"ServerGroup.capacityProvider.weight."+i,disabled:o,type:"number",className:"form-control input-sm no-spel",required:!0,value:a.weight,onChange:e=>n(i,e.target.valueAsNumber)})),o?"":ue.createElement("td",null,ue.createElement("div",{className:"form-control-static"},ue.createElement("a",{className:"btn-link sm-label",onClick:()=>r(i)},ue.createElement("span",{className:"glyphicon glyphicon-trash"}),ue.createElement("span",{className:"sr-only"},"Remove")))))}):o&&0==this.state.capacityProviderStrategy.length?ue.createElement("tr",null,ue.createElement("div",{className:"sm-label-left",style:{width:"200%"}},ue.createElement(he,{color:"warning"}," ","The cluster does not have a default capacity provider strategy defined. Set a default capacity provider strategy or use a custom strategy."))):"",h=this.state.ecsClusterName&&this.props.command.credentials&&this.props.command.region&&!o&&p.length>0?ue.createElement("button",{"data-test-id":"ServerGroup.addCapacityProvider",className:"btn btn-block btn-sm add-new",onClick:a},ue.createElement("span",{className:"glyphicon glyphicon-plus-sign"}),"Add New Capacity Provider"):!o&&l&&0==p.length?ue.createElement("div",{className:"sm-label-left",style:{width:"200%"}},ue.createElement(he,{color:"warning"}," The cluster does not have capacity providers defined. ")):"";return ue.createElement("div",null,(c.length>0||d.length>0)&&l?ue.createElement("div",null,g):"",ue.createElement("div",{className:"sm-label-left"},ue.createElement("b",null,"Capacity Provider Strategy"),ue.createElement(R,{id:"ecs.capacityProviderStrategy"})," ",ue.createElement("br",null),ue.createElement("span",null,"(",this.state.ecsClusterName,")")),ue.createElement("div",{className:"radio"},ue.createElement("label",null,ue.createElement("input",{"data-test-id":"ServerGroup.capacityProviders.default",type:"radio",checked:o,onClick:()=>i(!0),id:"computeOptionsLaunchType1"}),"Use cluster default")),ue.createElement("div",{className:"radio"},ue.createElement("label",null,ue.createElement("input",{"data-test-id":"ServerGroup.capacityProviders.custom",type:"radio",checked:!o,onClick:()=>i(!1),id:"computeOptionsCapacityProviders2"}),"Use custom (Advanced)")),l?ue.createElement("table",{className:"table table-condensed packed tags"},ue.createElement("thead",null,ue.createElement("tr",null,ue.createElement("th",{style:{width:"50%"}},"Provider name",ue.createElement(R,{id:"ecs.capacityProviderName"})),ue.createElement("th",{style:{width:"25%"}},"Base",ue.createElement(R,{id:"ecs.capacityProviderBase"})),ue.createElement("th",{style:{width:"25%"}},"Weight",ue.createElement(R,{id:"ecs.capacityProviderWeight"})))),ue.createElement("tbody",null,v),ue.createElement("tfoot",null,ue.createElement("tr",null,ue.createElement("td",{colSpan:4},h)))):ue.createElement("div",{className:"load medium"},ue.createElement("div",{className:"message"},"Loading capacity providers..."),ue.createElement("div",{className:"bars"},ue.createElement("div",{className:"bar"}),ue.createElement("div",{className:"bar"}),ue.createElement("div",{className:"bar"}))))}}const nt="spinnaker.ecs.serverGroup.configure.wizard.capacityProvider.react";t(nt,[]).component("ecsCapacityProviderReact",fe($(tt,"ecsCapacityProviderReact"),["command","notifyAngular","configureCommand"]));class at extends pe.Component{constructor(e){super(e),this.getIdToImageMap=()=>{const e=new Map;return this.props.command.backingData.filtered.images.forEach(t=>{e.set(t.imageId,t)}),e},this.getEmptyImageDescription=()=>({imageId:"",message:"",fromTrigger:!1,fromContext:!1,stageId:"",imageLabelOrSha:"",account:"",registry:"",repository:"",tag:""}),this.pushTargetGroupMapping=()=>{const e=this.state.targetGroupMappings;e.push({containerName:"",targetGroup:"",containerPort:80}),this.setState({targetGroupMappings:e})},this.updateContainerMappingImage=e=>{let t=this.getIdToImageMap().get(e.value);t||(t=this.getEmptyImageDescription()),this.props.notifyAngular("imageDescription",t),this.setState({imageDescription:t})},this.updateComputeUnits=e=>{this.props.notifyAngular("computeUnits",e),this.setState({computeUnits:e})},this.updateReservedMemory=e=>{this.props.notifyAngular("reservedMemory",e),this.setState({reservedMemory:e})},this.updateTargetGroupMappingTargetGroup=(e,t)=>{const n=this.state.targetGroupMappings;n[e].targetGroup=t.value,this.props.notifyAngular("targetGroupMappings",n),this.setState({targetGroupMappings:n}),this.updateDirtyTargetGroups()},this.updateTargetGroupMappingPort=(e,t)=>{const n=this.state.targetGroupMappings;n[e].containerPort=t,this.props.notifyAngular("targetGroupMappings",n),this.setState({targetGroupMappings:n})},this.removeTargetGroupMapping=e=>{const t=this.state.targetGroupMappings;t.splice(e,1),this.props.notifyAngular("targetGroupMappings",t),this.setState({targetGroupMappings:t})},this.updateDirtyTargetGroups=()=>{this.props.command.viewState.dirty.targetGroups=[]};const t=this.props.command;let n="";t.containerMappings&&t.containerMappings.length>0&&(n=t.containerMappings[0].containerName);let a=[];t.targetGroupMappings&&t.targetGroupMappings.length>0&&(a=t.targetGroupMappings),t.targetGroup&&t.targetGroup.length>0&&(a.push({containerName:t.loadBalancedContainer||n,targetGroup:t.targetGroup,containerPort:t.containerPort}),t.targetGroup="",t.loadBalancedContainer=""),t.targetGroupMappings=re(a,W),t.containerMappings=null,this.state={imageDescription:t.imageDescription?t.imageDescription:this.getEmptyImageDescription(),computeUnits:t.computeUnits,reservedMemory:t.reservedMemory,dockerImages:t.backingData&&t.backingData.filtered?t.backingData.filtered.images:[],targetGroupMappings:t.targetGroupMappings,targetGroupsAvailable:t.backingData&&t.backingData.filtered?t.backingData.filtered.targetGroups:[]},this.state.targetGroupMappings.forEach(e=>{e.containerName=""})}componentDidMount(){this.props.configureCommand("1").then(()=>{this.setState({dockerImages:this.props.command.backingData.filtered.images,targetGroupsAvailable:this.props.command.backingData.filtered.targetGroups})})}render(){const e=this.removeTargetGroupMapping,t=this.updateContainerMappingImage,n=this.updateTargetGroupMappingTargetGroup,a=this.updateTargetGroupMappingPort,r=this.updateComputeUnits,i=this.updateReservedMemory,s=this.props.command.viewState.dirty&&this.props.command.viewState.dirty.targetGroups?this.props.command.viewState.dirty.targetGroups:[],o=this.state.dockerImages.map(function(e){let t="";return(e.fromTrigger||e.fromContext)&&(t=e.fromTrigger?"(TRIGGER) ":"(FIND IMAGE RESULT) "),{label:`${t} (${e.imageId})`,value:e.imageId}}),l=s?s.map(function(e,t){return pe.createElement("li",{key:t},e)}):"",c=pe.createElement("div",{className:"alert alert-warning"},pe.createElement("p",null,pe.createElement("i",{className:"fa fa-exclamation-triangle"}),"The following target groups could not be found in the selected account/region/VPC and were removed:"),pe.createElement("ul",null,l),pe.createElement("br",null),pe.createElement("p",{className:"text-left"},"Please select the target group(s) from the dropdown to resolve this error.")),d=this.state.targetGroupsAvailable.length?pe.createElement("button",{className:"btn btn-block btn-sm add-new","data-test-id":"ContainerInputs.targetGroupAdd",onClick:this.pushTargetGroupMapping},pe.createElement("span",{className:"glyphicon glyphicon-plus-sign"}),"Add New Target Group Mapping"):pe.createElement("div",{className:"sm-label-left"},pe.createElement(he,{color:"warning"},"No target groups found in the selected account/region/VPC")),p=this.state.targetGroupsAvailable.map(function(e){return{label:`${e}`,value:e}}),u=this.state.targetGroupMappings.map(function(t,r){return pe.createElement("tr",{key:r},pe.createElement("td",{"data-test-id":"ContainerInputs.targetGroup"},pe.createElement(M,{placeholder:"Select a target group to use...",options:p,value:t.targetGroup.toString(),onChange:e=>n(r,e),clearable:!1})),pe.createElement("td",null,pe.createElement("input",{"data-test-id":"ContainerInputs.targetGroupPort",type:"number",className:"form-control input-sm no-spel",required:!0,value:t.containerPort.toString(),onChange:e=>a(r,e.target.valueAsNumber)})),pe.createElement("td",null,pe.createElement("div",{className:"form-control-static"},pe.createElement("a",{className:"btn-link sm-label","data-test-id":"ContainerInputs.targetGroupRemove",onClick:()=>e(r)},pe.createElement("span",{className:"glyphicon glyphicon-trash"}),pe.createElement("span",{className:"sr-only"},"Remove")))))});return pe.createElement("div",{className:"container-fluid form-horizontal"},s.length>0?pe.createElement("div",null,c):"",pe.createElement("div",{className:"form-group"},pe.createElement("div",{className:"col-md-3 sm-label-right"},pe.createElement("b",null,"Container Image"),pe.createElement(R,{id:"ecs.containerMappingImage"})),pe.createElement("div",{className:"col-md-9","data-test-id":"ContainerInputs.containerImage"},pe.createElement(M,{placeholder:"Select an image to use...",options:o,value:this.state.imageDescription.imageId,onChange:e=>{t(e)},clearable:!1}))),pe.createElement("div",{className:"form-group"},pe.createElement("div",{className:"col-md-3 sm-label-right"},pe.createElement("b",null,"Compute Units"),pe.createElement(R,{id:"ecs.capacity.reserved.computeUnits"})),pe.createElement("div",{className:"col-md-9",style:{width:"100px"}},pe.createElement("input",{"data-test-id":"ContainerInputs.computeUnits",type:"number",className:"form-control input-sm no-spel",required:!1,value:this.state.computeUnits,onChange:e=>r(e.target.valueAsNumber)}))),pe.createElement("div",{className:"form-group"},pe.createElement("div",{className:"col-md-3 sm-label-right"},pe.createElement("b",null,"Reserved Memory"),pe.createElement(R,{id:"ecs.capacity.reserved.memory"})),pe.createElement("div",{className:"col-md-9",style:{width:"100px"}},pe.createElement("input",{"data-test-id":"ContainerInputs.reservedMemory",type:"number",className:"form-control input-sm no-spel",required:!1,value:this.state.reservedMemory,onChange:e=>i(e.target.valueAsNumber)}))),pe.createElement("div",{className:"form-group"},pe.createElement("div",{className:"sm-label-left"},pe.createElement("b",null,"Target Group Mappings"),pe.createElement(R,{id:"ecs.targetGroupMappings"})),pe.createElement("form",{name:"ecsContainerTargetGroupMappings"},pe.createElement("table",{className:"table table-condensed packed tags"},pe.createElement("thead",null,pe.createElement("tr",{key:"header"},pe.createElement("th",{style:{width:"80%"}},"Target group",pe.createElement(R,{id:"ecs.loadBalancer.targetGroup"})),pe.createElement("th",{style:{width:"20%"}},"Target port",pe.createElement(R,{id:"ecs.loadbalancing.targetPort"})),pe.createElement("th",null))),pe.createElement("tbody",null,u),pe.createElement("tfoot",null,pe.createElement("tr",null,pe.createElement("td",{colSpan:4},d)))))))}}const rt="spinnaker.ecs.serverGroup.configure.wizard.container.react";t(rt,[]).component("containerReact",fe($(at,"containerReact"),["command","notifyAngular","configureCommand"]));const it="spinnaker.ecs.serverGroup.configure.wizard.horizontalScaling.component";t(it,[]).component("ecsServerGroupHorizontalScaling",{bindings:{command:"=",application:"=",capacityProviderState:"=",notifyAngular:"=",configureCommand:"="},templateUrl:"ecs/src/serverGroup/configure/wizard/horizontalScaling/horizontalScaling.component.html"}),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/serverGroup/configure/wizard/horizontalScaling/horizontalScaling.component.html",'<div class="container-fluid form-horizontal">\n <div class="form-group">\n <div class="col-md-4 sm-label-right">\n <b>Compute options</b>\n <help-field key="ecs.computeOptions"></help-field>\n </div>\n <div class="col-md-2 radio">\n <label>\n <input\n data-test-id="ServerGroup.computeOptionsLaunchType"\n type="radio"\n ng-model="$ctrl.capacityProviderState.useCapacityProviders"\n ng-value="false"\n ng-click="$ctrl.capacityProviderState.updateComputeOption(\'launchType\')"\n id="computeOptionsLaunchType"\n />\n Launch type\n </label>\n </div>\n <div class="col-md-1 radio">\n <label>\n <input\n data-test-id="ServerGroup.computeOptionsCapacityProviders"\n type="radio"\n ng-model="$ctrl.capacityProviderState.useCapacityProviders"\n ng-value="true"\n ng-click="$ctrl.capacityProviderState.updateComputeOption(\'capacityProviders\')"\n id="computeOptionsCapacityProviders"\n />\n Capacity Providers\n </label>\n </div>\n </div>\n\n <div class="form-group" ng-if="$ctrl.capacityProviderState.useCapacityProviders">\n <ecs-capacity-provider-react\n command="$ctrl.command"\n notify-angular="$ctrl.notifyAngular"\n configure-command="$ctrl.configureCommand"\n ></ecs-capacity-provider-react>\n </div>\n\n <div class="form-group" ng-if="!$ctrl.capacityProviderState.useCapacityProviders" style="padding-top: 10px">\n <div class="col-md-5 sm-label-right">\n Launch Type\n <help-field key="ecs.launchtype"></help-field>\n </div>\n <div class="col-md-3" data-test-id="ServerGroup.launchType">\n <ui-select ng-model="$ctrl.command.launchType" class="form-control input-sm">\n <ui-select-match placeholder="Select...">{{ $select.selected }}</ui-select-match>\n <ui-select-choices repeat="launchType in $ctrl.command.backingData.launchTypes | filter: $select.search">\n <span ng-bind-html="launchType | highlight: $select.search"></span>\n </ui-select-choices>\n </ui-select>\n </div>\n </div>\n\n <hr />\n\n <div class="form-group">\n <div class="col-md-5 sm-label-right">\n Desired capacity\n <help-field key="ecs.capacity.desired"></help-field>\n </div>\n <div class="col-md-2">\n <input\n type="number"\n class="form-control input-sm no-spel"\n name="capacity"\n ng-model="$ctrl.command.capacity.desired"\n />\n </div>\n </div>\n\n <div class="form-group">\n <div class="col-md-5 sm-label-right">\n Minimum\n <help-field key="ecs.capacity.minimum"></help-field>\n </div>\n <div class="col-md-2">\n <input type="number" class="form-control input-sm no-spel" name="min" ng-model="$ctrl.command.capacity.min" />\n </div>\n </div>\n\n <div class="form-group">\n <div class="col-md-5 sm-label-right">\n Maximum\n <help-field key="ecs.capacity.maximum"></help-field>\n </div>\n <div class="col-md-2">\n <input type="number" class="form-control input-sm no-spel" name="max" ng-model="$ctrl.command.capacity.max" />\n </div>\n </div>\n\n <div class="form-group">\n <div class="col-md-12 checkbox">\n <label>\n <input\n type="checkbox"\n ng-model="$ctrl.command.useSourceCapacity"\n ng-change="$ctrl.command.preferSourceCapacity=$ctrl.command.useSourceCapacity"\n />\n <b>If available, use the previous server group\'s capacity</b>\n </label>\n <help-field key="ecs.capacity.overwrite"></help-field>\n </div>\n </div>\n\n <div class="form-group">\n <div class="col-md-12 checkbox">\n <label>\n <input type="checkbox" ng-model="$ctrl.command.copySourceScalingPoliciesAndActions" />\n <b>If available, copy the previous server group\'s autoscaling policies</b>\n </label>\n <help-field key="ecs.capacity.copySourceScalingPoliciesAndActions"></help-field>\n </div>\n </div>\n</div>\n')}]);const st="spinnaker.ecs.serverGroup.configure.basicSettings";e.module(st,[V,_]).controller("ecsServerGroupBasicSettingsCtrl",["$scope","$controller","$uibModalStack","$state",function(t,n,a,r){e.extend(this,n("BasicSettingsMixin",{$scope:t,$uibModalStack:a,$state:r})),t.$watch("form.$valid",function(e){e?(x.markClean("basicSettings"),x.markComplete("basicSettings")):x.markIncomplete("basicSettings")})}]);const ot="spinnaker.ecs.serverGroup.configure.wizard.logging.component";t(ot,[]).component("ecsServerGroupLogging",{bindings:{command:"=",application:"="},templateUrl:"ecs/src/serverGroup/configure/wizard/logging/logging.component.html"}),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/serverGroup/configure/wizard/logging/logging.component.html",'<div class="container-fluid form-horizontal">\n <div class="form-group">\n <div class="col-md-5 sm-label-right">\n <b>Log driver (Optional)</b> <help-field key="ecs.logDriver"></help-field>\n </div>\n <div class="col-md-7">\n <ui-select ng-model="$ctrl.command.logDriver" class="form-control input-sm" data-test-id="Logging.logDriver">\n <ui-select-match>{{ $select.selected }}</ui-select-match>\n <ui-select-choices\n repeat="item in [\'None\', \'awslogs\', \'fluentd\', \'gelf\', \'journald\', \'json-file\', \'logentries\', \'splunk\', \'sumologic\', \'syslog\'] | filter: $select.search"\n >\n <span ng-bind-html="item"></span>\n </ui-select-choices>\n </ui-select>\n </div>\n </div>\n\n <div class="form-group" ng-if="$ctrl.command.logDriver && $ctrl.command.logDriver !== \'None\'">\n <div class="sm-label-left">\n <b>Logging options (optional)</b>\n <help-field key="ecs.logOptions"></help-field>\n </div>\n <map-editor model="$ctrl.command.logOptions" allow-empty="true"></map-editor>\n </div>\n\n <div class="form-group" ng-if="!$ctrl.command.logDriver || $ctrl.command.logDriver == \'None\'">\n Logging options are not available for your log driver selection.\n </div>\n</div>\n')}]);class lt extends pe.Component{constructor(e){super(e),this.updateNetworkMode=e=>{const t=e.value,n=this.props.command;this.props.notifyAngular("networkMode",t),this.setState({networkMode:t,subnetTypesAvailable:n.backingData&&n.backingData.filtered&&n.backingData.filtered.subnetTypes?n.backingData.filtered.subnetTypes:[]})},this.updateSecurityGroups=e=>{const t=Array.isArray(e)?e.map(e=>e.value):[];this.props.notifyAngular("securityGroupNames",t),this.setState({securityGroupNames:t})},this.updateSubnetTypes=e=>{const t=this.props.command,n=Array.isArray(e)?e.map(e=>e.value):[];this.props.notifyAngular("subnetTypes",n),t.subnetTypeChanged(t),this.setState({subnetTypes:n,securityGroupsAvailable:t.backingData&&t.backingData.filtered&&t.backingData.filtered.securityGroupNames?t.backingData.filtered.securityGroupNames:[]})},this.updateAssociatePublicIpAddress=e=>{this.props.notifyAngular("associatePublicIpAddress",e),this.setState({associatePublicIpAddress:e})};const t=this.props.command;let n=[];t.subnetTypes&&t.subnetTypes.length>0&&(n=t.subnetTypes),t.subnetType&&t.subnetType.length>0&&(n.push(t.subnetType),t.subnetType=""),t.subnetTypes=re(n,W),this.state={associatePublicIpAddress:t.associatePublicIpAddress,networkMode:t.networkMode,networkModesAvailable:t.backingData&&t.backingData.networkModes?t.backingData.networkModes:[],securityGroupNames:t.securityGroupNames,securityGroupsAvailable:t.backingData&&t.backingData.filtered&&t.backingData.filtered.securityGroupNames?t.backingData.filtered.securityGroupNames:[],subnetTypes:t.subnetTypes,subnetTypesAvailable:t.backingData&&t.backingData.filtered&&t.backingData.filtered.subnetTypes?t.backingData.filtered.subnetTypes:[]}}componentDidMount(){const e=this.props.command;this.props.configureCommand("1").then(()=>{this.setState({networkModesAvailable:e.backingData&&e.backingData.networkModes?e.backingData.networkModes:[],securityGroupsAvailable:e.backingData&&e.backingData.filtered&&e.backingData.filtered.securityGroupNames?e.backingData.filtered.securityGroupNames:[],subnetTypesAvailable:e.backingData&&e.backingData.filtered&&e.backingData.filtered.subnetTypes?e.backingData.filtered.subnetTypes:[]})})}render(){const e=this.updateAssociatePublicIpAddress,t=this.updateNetworkMode,n=this.updateSecurityGroups,a=this.updateSubnetTypes,r=this.state.networkModesAvailable.map(function(e){return{label:`${e}`,value:e}}),i=this.state.securityGroupsAvailable.map(function(e){return{label:`${e}`,value:e}}),s=this.state.subnetTypesAvailable.map(function(e){return{label:`${e.purpose} (${e.vpcId})`,value:e.purpose}}),o=this.state.subnetTypesAvailable.length?pe.createElement(M,{multi:!0,options:s,value:this.state.subnetTypes,onChange:e=>{a(e)}}):pe.createElement(he,{color:"warning"},"No account was selected, or no subnet types are available for this account"),l=this.state.securityGroupsAvailable.length?pe.createElement(M,{multi:!0,options:i,value:this.state.securityGroupNames,onChange:e=>{n(e)}}):pe.createElement(he,{color:"warning"},"No security groups found in the selected account/region"),c="awsvpc"===this.state.networkMode?pe.createElement("div",{className:"form-group"},pe.createElement("div",{className:"form-group"},pe.createElement("div",{className:"col-md-3 sm-label-right"},pe.createElement("b",null,"VPC Subnet"),pe.createElement(R,{key:"ecs.subnet"})),pe.createElement("div",{className:"col-md-9","data-test-id":"Networking.subnetType"},o)),pe.createElement("div",{className:"form-group"},pe.createElement("div",{className:"col-md-3 sm-label-right"},pe.createElement("b",null,"Security Groups"),pe.createElement(R,{key:"ecs.securityGroups"})),pe.createElement("div",{className:"col-md-9","data-test-id":"Networking.securityGroups"},l)),pe.createElement("div",{className:"form-group"},pe.createElement("div",{className:"col-md-3 sm-label-right"},pe.createElement("b",null,"Associate Public IP Address"),pe.createElement(R,{key:"ecs.publicip"})),pe.createElement("div",{className:"col-md-1 radio"},pe.createElement("label",null,pe.createElement("input",{"data-test-id":"Networking.associatePublicIpAddressTrue",type:"radio",value:"true",id:"associatePublicIpAddressTrue",checked:!0===this.state.associatePublicIpAddress,onChange:()=>e(!0)}),"Yes")),pe.createElement("div",{className:"col-md-1 radio"},pe.createElement("label",null,pe.createElement("input",{"data-test-id":"Networking.associatePublicIpAddressFalse",type:"radio",value:"false",id:"associatePublicIpAddressFalse",checked:!1===this.state.associatePublicIpAddress,onChange:()=>e(!1)}),"No")))):pe.createElement("div",{className:"col-md-3 sm-label-right"});return pe.createElement("div",{className:"networking-fluid form-horizontal"},pe.createElement("div",{className:"form-group"},pe.createElement("div",{className:"form-group"},pe.createElement("div",{className:"col-md-3 sm-label-right"},pe.createElement("b",null,"Network Mode"),pe.createElement(R,{id:"ecs.networkMode"})),pe.createElement("div",{className:"col-md-9","data-test-id":"Networking.networkMode"},pe.createElement(M,{placeholder:"Select a network mode to use ...",options:r,value:this.state.networkMode,onChange:e=>{t(e)}})))),c)}}const ct="spinnaker.ecs.serverGroup.configure.wizard.networking.react";t(ct,[]).component("ecsNetworkingReact",fe($(lt,"ecsNetworkingReact"),["command","notifyAngular","configureCommand"]));class dt extends ue.Component{constructor(e){super(e),this.getNameToRegistryMap=()=>{const e=new Map;return this.props.command.backingData.filtered.serviceDiscoveryRegistries.forEach(t=>{e.set(t.displayName,t)}),e},this.getEmptyRegistry=()=>({account:"",region:"",name:"",id:"",arn:"",displayName:""}),this.updateServiceDiscoveryRegistry=(e,t)=>{let n=this.getNameToRegistryMap().get(t.value);n||(n=this.getEmptyRegistry());const a=this.state.serviceDiscoveryAssociations;a[e].registry=n,this.props.notifyAngular("serviceDiscoveryAssociations",a),this.setState({serviceDiscoveryAssociations:a})},this.updateServiceDiscoveryPort=(e,t)=>{const n=this.state.serviceDiscoveryAssociations;n[e].containerPort=t,this.props.notifyAngular("serviceDiscoveryAssociations",n),this.setState({serviceDiscoveryAssociations:n})},this.updateServiceDiscoveryContainerName=(e,t)=>{const n=this.state.serviceDiscoveryAssociations;n[e].containerName=t,this.props.notifyAngular("serviceDiscoveryAssociations",n),this.setState({serviceDiscoveryAssociations:n})},this.pushServiceDiscoveryAssociation=()=>{const e=this.state.serviceDiscoveryAssociations;e.push({registry:this.getEmptyRegistry(),containerPort:80,containerName:""}),this.setState({serviceDiscoveryAssociations:e})},this.removeServiceDiscoveryAssociations=e=>{const t=this.state.serviceDiscoveryAssociations;t.splice(e,1),this.props.notifyAngular("serviceDiscoveryAssociations",t),this.setState({serviceDiscoveryAssociations:t})};const t=this.props.command;this.state={serviceDiscoveryAssociations:t.serviceDiscoveryAssociations,serviceDiscoveryRegistriesAvailable:t.backingData&&t.backingData.filtered?t.backingData.filtered.serviceDiscoveryRegistries:[],useTaskDefinitionArtifact:t.useTaskDefinitionArtifact},this.state.useTaskDefinitionArtifact||this.state.serviceDiscoveryAssociations.forEach(e=>{e.containerName=null})}componentDidMount(){this.props.configureCommand("1").then(()=>{this.setState({serviceDiscoveryRegistriesAvailable:this.props.command.backingData.filtered.serviceDiscoveryRegistries})})}render(){const e=this.removeServiceDiscoveryAssociations,t=this.updateServiceDiscoveryRegistry,n=this.updateServiceDiscoveryPort,a=this.updateServiceDiscoveryContainerName,r=this.state.serviceDiscoveryRegistriesAvailable.map(function(e){return{label:`${e.displayName}`,value:e.displayName}}),i=this.state.useTaskDefinitionArtifact,s=this.state.serviceDiscoveryAssociations.map(function(s,o){return ue.createElement("tr",{key:o},i&&ue.createElement("td",null,ue.createElement("input",{className:"form-control input-sm",placeholder:"Enter a container name ...",required:!0,value:s.containerName,onChange:e=>a(o,e.target.value)})),ue.createElement("td",null,ue.createElement(M,{placeholder:"Select a registry...",options:r,value:s.registry.displayName.toString(),onChange:e=>t(o,e),clearable:!1,required:!0})),ue.createElement("td",null,ue.createElement("input",{type:"number",className:"form-control input-sm no-spel",required:!0,value:s.containerPort,onChange:e=>n(o,e.target.valueAsNumber)})),ue.createElement("td",null,ue.createElement("div",{className:"form-control-static"},ue.createElement("a",{className:"btn-link sm-label",onClick:()=>e(o)},ue.createElement("span",{className:"glyphicon glyphicon-trash"}),ue.createElement("span",{className:"sr-only"},"Remove")))))}),o=this.state.serviceDiscoveryRegistriesAvailable.length?ue.createElement("button",{className:"btn btn-block btn-sm add-new",onClick:this.pushServiceDiscoveryAssociation},ue.createElement("span",{className:"glyphicon glyphicon-plus-sign"}),"Add New Service Registry"):ue.createElement("div",{className:"sm-label-left"},ue.createElement(he,{color:"warning"},"No registries found in the selected account/region/VPC"));return ue.createElement("div",{className:"container-fluid form-horizontal"},ue.createElement("div",{className:"form-group"},ue.createElement("div",{className:"sm-label-left"},ue.createElement("b",null,"Service Registries (optional)"),ue.createElement(R,{id:"ecs.serviceDiscovery"})),ue.createElement("form",{name:"ecsServiceDiscoveryRegistryMappings"},ue.createElement("table",{className:"table table-condensed packed tags"},ue.createElement("thead",null,ue.createElement("tr",null,i&&ue.createElement("th",{style:{width:"30%"}},"Container name",ue.createElement(R,{id:"ecs.serviceDiscoveryContainerName"})),i?ue.createElement("th",{style:{width:"55%"}},"Registry",ue.createElement(R,{id:"ecs.serviceDiscoveryRegistry"})):ue.createElement("th",{style:{width:"80%"}},"Registry",ue.createElement(R,{id:"ecs.serviceDiscoveryRegistry"})),ue.createElement("th",{style:{width:"15%"}},"Port",ue.createElement(R,{id:"ecs.serviceDiscoveryContainerPort"})),ue.createElement("th",null))),ue.createElement("tbody",null,s),ue.createElement("tfoot",null,ue.createElement("tr",null,ue.createElement("td",{colSpan:4},o)))))))}}const pt="spinnaker.ecs.serverGroup.configure.wizard.serviceDiscovery.react";t(pt,[]).component("serviceDiscoveryReact",fe($(dt,"serviceDiscoveryReact"),["command","notifyAngular","configureCommand"]));class ut extends ue.Component{constructor(e){super(e),this.getIdToImageMap=()=>{const e=new Map;return this.props.command.backingData.filtered.images.forEach(t=>{e.set(t.imageId,t)}),e},this.getEmptyImageDescription=()=>({imageId:"",message:"",fromTrigger:!1,fromContext:!1,stageId:"",imageLabelOrSha:"",account:"",registry:"",repository:"",tag:""}),this.excludedArtifactTypePatterns=[B.KUBERNETES,B.DOCKER_IMAGE,B.FRONT50_PIPELINE_TEMPLATE],this.onExpectedArtifactSelected=e=>{const t={artifactId:e};this.props.notifyAngular("taskDefinitionArtifact",t),this.setState({taskDefArtifact:t})},this.onArtifactEdited=e=>{const t={artifact:e};this.props.notifyAngular("taskDefinitionArtifact",t),this.setState({taskDefArtifact:t})},this.pushMapping=()=>{const e=this.state.containerMappings;e.push({containerName:"",imageDescription:this.getEmptyImageDescription()}),this.setState({containerMappings:e})},this.pushTargetGroupMapping=()=>{const e=this.state.targetGroupMappings;e.push({containerName:"",targetGroup:"",containerPort:80}),this.setState({targetGroupMappings:e})},this.updateContainerMappingName=(e,t)=>{const n=this.state.containerMappings;n[e].containerName=t,this.props.notifyAngular("containerMappings",n),this.setState({containerMappings:n})},this.updateContainerMappingImage=(e,t)=>{let n=this.getIdToImageMap().get(t.value);n||(n=this.getEmptyImageDescription());const a=this.state.containerMappings;a[e].imageDescription=n,this.props.notifyAngular("containerMappings",a),this.setState({containerMappings:a})},this.updateTargetGroupMappingTargetGroup=(e,t)=>{const n=this.state.targetGroupMappings;n[e].targetGroup=t.value,this.props.notifyAngular("targetGroupMappings",n),this.setState({targetGroupMappings:n})},this.updateTargetGroupMappingContainer=(e,t)=>{const n=this.state.targetGroupMappings;n[e].containerName=t,this.props.notifyAngular("targetGroupMappings",n),this.setState({targetGroupMappings:n})},this.updateTargetGroupMappingPort=(e,t)=>{const n=this.state.targetGroupMappings;n[e].containerPort=t,this.props.notifyAngular("targetGroupMappings",n),this.setState({targetGroupMappings:n})},this.removeMapping=e=>{const t=this.state.containerMappings;t.splice(e,1),this.props.notifyAngular("containerMappings",t),this.setState({containerMappings:t})},this.removeTargetGroupMapping=e=>{const t=this.state.targetGroupMappings;t.splice(e,1),this.props.notifyAngular("targetGroupMappings",t),this.setState({targetGroupMappings:t})},this.updateEvaluateTaskDefArtifactFlag=()=>{this.props.notifyAngular("evaluateTaskDefinitionArtifactExpressions",!this.props.command.evaluateTaskDefinitionArtifactExpressions),this.setState({evaluateTaskDefinitionArtifactExpressions:!this.props.command.evaluateTaskDefinitionArtifactExpressions})};const t=this.props.command;let n="";t.containerMappings&&t.containerMappings.length>0&&(n=t.containerMappings[0].containerName);let a=[];t.targetGroupMappings&&t.targetGroupMappings.length>0&&(a=t.targetGroupMappings),t.targetGroup&&t.targetGroup.length>0&&(a.push({containerName:t.loadBalancedContainer||n,targetGroup:t.targetGroup,containerPort:t.containerPort}),t.targetGroup="",t.loadBalancedContainer=""),t.targetGroupMappings=re(a,W),this.state={taskDefArtifact:t.taskDefinitionArtifact,containerMappings:t.containerMappings?t.containerMappings:[],targetGroupMappings:t.targetGroupMappings,targetGroupsAvailable:t.backingData&&t.backingData.filtered?t.backingData.filtered.targetGroups:[],dockerImages:t.backingData&&t.backingData.filtered?t.backingData.filtered.images:[],loadBalancedContainer:t.loadBalancedContainer||n,taskDefArtifactAccount:t.taskDefinitionArtifactAccount,evaluateTaskDefinitionArtifactExpressions:t.evaluateTaskDefinitionArtifactExpressions}}componentDidMount(){this.props.configureCommand("1").then(()=>{this.setState({dockerImages:this.props.command.backingData.filtered.images,targetGroupsAvailable:this.props.command.backingData.filtered.targetGroups})})}render(){const{command:e}=this.props,t=this.removeMapping,n=this.removeTargetGroupMapping,a=this.updateContainerMappingName,r=this.updateContainerMappingImage,i=this.updateTargetGroupMappingContainer,s=this.updateTargetGroupMappingTargetGroup,o=this.updateTargetGroupMappingPort,l=this.updateEvaluateTaskDefArtifactFlag,c=this.state.dockerImages.map(function(e){let t="";return(e.fromTrigger||e.fromContext)&&(t=e.fromTrigger?"(TRIGGER) ":"(FIND IMAGE RESULT) "),{label:`${t} (${e.imageId})`,value:e.imageId}}),d=this.state.targetGroupsAvailable.map(function(e){return{label:`${e}`,value:e}}),p=this.state.containerMappings.map(function(e,n){return ue.createElement("tr",{key:n},ue.createElement("td",null,ue.createElement("input",{"data-test-id":"Artifacts.containerName",className:"form-control input-sm",required:!0,placeholder:"enter container name...",value:e.containerName.toString(),onChange:e=>a(n,e.target.value)})),ue.createElement("td",{"data-test-id":"Artifacts.containerImage"},ue.createElement(M,{placeholder:"Select an image to use...",options:c,value:e.imageDescription.imageId,onChange:e=>{r(n,e)},clearable:!1})),ue.createElement("td",null,ue.createElement("div",{className:"form-control-static"},ue.createElement("a",{className:"btn-link sm-label","data-test-id":"Artifacts.containerRemove",onClick:()=>t(n)},ue.createElement("span",{className:"glyphicon glyphicon-trash"}),ue.createElement("span",{className:"sr-only"},"Remove")))))}),u=this.state.targetGroupMappings.map(function(e,t){return ue.createElement("tr",{key:t},ue.createElement("td",null,ue.createElement("input",{"data-test-id":"Artifacts.targetGroupContainer",className:"form-control input-sm",required:!0,placeholder:"Enter a container name ...",value:e.containerName.toString(),onChange:e=>i(t,e.target.value)})),ue.createElement("td",{"data-test-id":"Artifacts.targetGroup"},ue.createElement(M,{placeholder:"Select a target group to use...",options:d,value:e.targetGroup.toString(),onChange:e=>s(t,e),clearable:!1})),ue.createElement("td",null,ue.createElement("input",{"data-test-id":"Artifacts.targetGroupPort",type:"number",className:"form-control input-sm no-spel",required:!0,value:e.containerPort.toString(),onChange:e=>o(t,e.target.valueAsNumber)})),ue.createElement("td",null,ue.createElement("div",{className:"form-control-static"},ue.createElement("a",{className:"btn-link sm-label","data-test-id":"Artifacts.targetGroupRemove",onClick:()=>n(t)},ue.createElement("span",{className:"glyphicon glyphicon-trash"}),ue.createElement("span",{className:"sr-only"},"Remove")))))}),m=this.state.targetGroupsAvailable.length?ue.createElement("button",{className:"btn btn-block btn-sm add-new","data-test-id":"Artifacts.targetGroupAdd",onClick:this.pushTargetGroupMapping},ue.createElement("span",{className:"glyphicon glyphicon-plus-sign"}),"Add New Target Group Mapping"):ue.createElement("div",{className:"sm-label-left"},ue.createElement(he,{color:"warning"},"No target groups found in the selected account/region/VPC"));return ue.createElement("div",{className:"container-fluid form-horizontal"},ue.createElement("div",{className:"form-group"},ue.createElement("div",{className:"col-md-12"},ue.createElement(F,{artifact:this.state.taskDefArtifact.artifact,excludedArtifactTypePatterns:this.excludedArtifactTypePatterns,expectedArtifactId:this.state.taskDefArtifact.artifactId,label:"Artifact",helpKey:"ecs.taskDefinitionArtifact",onExpectedArtifactSelected:e=>this.onExpectedArtifactSelected(e.id),onArtifactEdited:this.onArtifactEdited,pipeline:e.viewState.pipeline,stage:e.viewState.currentStage}))),ue.createElement(L,{groupClassName:"form-group evaluateTaskDef",label:"Expression Evaluation",helpKey:"ecs.evaluateExpression",labelColumns:5,fieldColumns:7},ue.createElement(O,{checked:!0===e.evaluateTaskDefinitionArtifactExpressions,onChange:()=>{l()},text:"Evaluate SpEL expressions in artifact"})),ue.createElement("div",{className:"form-group"},ue.createElement("div",{className:"sm-label-left"},ue.createElement("b",null,"Container Mappings"),ue.createElement(R,{id:"ecs.containerMappings"})),ue.createElement("form",{name:"ecsTaskDefinitionContainerMappings"},ue.createElement("table",{className:"table table-condensed packed tags"},ue.createElement("thead",null,ue.createElement("tr",{key:"header"},ue.createElement("th",{style:{width:"30%"}},"Container name",ue.createElement(R,{id:"ecs.containerMappingName"})),ue.createElement("th",{style:{width:"70%"}},"Container image",ue.createElement(R,{id:"ecs.containerMappingImage"})),ue.createElement("th",null))),ue.createElement("tbody",null,p),ue.createElement("tfoot",null,ue.createElement("tr",null,ue.createElement("td",{colSpan:3},ue.createElement("button",{className:"btn btn-block btn-sm add-new","data-test-id":"Artifacts.containerAdd",onClick:this.pushMapping},ue.createElement("span",{className:"glyphicon glyphicon-plus-sign"}),"Add New Container Mapping"))))))),ue.createElement("div",{className:"form-group"},ue.createElement("div",{className:"sm-label-left"},ue.createElement("b",null,"Target Group Mappings"),ue.createElement(R,{id:"ecs.targetGroupMappings"})),ue.createElement("form",{name:"ecsTaskDefinitionTargetGroupMappings"},ue.createElement("table",{className:"table table-condensed packed tags"},ue.createElement("thead",null,ue.createElement("tr",{key:"header"},ue.createElement("th",{style:{width:"30%"}},"Container name",ue.createElement(R,{id:"ecs.loadBalancedContainer"})),ue.createElement("th",{style:{width:"55%"}},"Target group",ue.createElement(R,{id:"ecs.loadBalancer.targetGroup"})),ue.createElement("th",{style:{width:"15%"}},"Target port",ue.createElement(R,{id:"ecs.loadbalancing.targetPort"})),ue.createElement("th",null))),ue.createElement("tbody",null,u),ue.createElement("tfoot",null,ue.createElement("tr",null,ue.createElement("td",{colSpan:4},m)))))))}}const mt="spinnaker.ecs.serverGroup.configure.wizard.taskDefinition.react";t(mt,[]).component("taskDefinitionReact",fe($(ut,"taskDefinitionReact"),["command","notifyAngular","configureCommand"]));const gt="spinnaker.ecs.serverGroup.resize";t(gt,[]).component("ecsResizeCapacity",{bindings:{command:"=",currentSize:"="},templateUrl:"ecs/src/serverGroup/details/resize/resizeCapacity.component.html",controller:()=>{}}),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/serverGroup/details/resize/resizeCapacity.component.html",'<div ng-if="$ctrl.command.advancedMode">\n <div class="form-group">\n <div class="col-md-12">\n <p>Sets up auto-scaling for this server group.</p>\n <p>To disable auto-scaling, use the <a href ng-click="$ctrl.command.advancedMode = false">Simple Mode</a>.</p>\n </div>\n </div>\n <div class="form-group">\n <div class="col-md-2 col-md-offset-3"><b>Min</b></div>\n <div class="col-md-2"><b>Max</b></div>\n <div class="col-md-2"><b>Desired</b></div>\n </div>\n <div class="form-group">\n <div class="col-md-3 sm-label-right">Current</div>\n <div class="col-md-2">\n <input type="number" class="form-control input-sm" ng-model="$ctrl.currentSize.min" readonly />\n </div>\n <div class="col-md-2">\n <input type="number" class="form-control input-sm" ng-model="$ctrl.currentSize.max" readonly />\n </div>\n <div class="col-md-2">\n <input type="number" class="form-control input-sm" ng-model="$ctrl.currentSize.desired" readonly />\n </div>\n </div>\n <div class="form-group">\n <div class="col-md-3 sm-label-right">Resize to</div>\n <div class="col-md-2">\n <input\n type="number"\n class="form-control input-sm"\n ng-model="$ctrl.command.min"\n min="0"\n required\n max="{{ $ctrl.command.max }}"\n />\n </div>\n <div class="col-md-2">\n <input\n type="number"\n class="form-control input-sm"\n ng-model="$ctrl.command.max"\n required\n min="{{ $ctrl.command.min }}"\n />\n </div>\n <div class="col-md-2">\n <input\n type="number"\n class="form-control input-sm"\n ng-model="$ctrl.command.desired"\n required\n min="{{ $ctrl.command.min }}"\n max="{{ $ctrl.command.max }}"\n />\n </div>\n </div>\n</div>\n<div ng-if="!$ctrl.command.advancedMode">\n <div class="form-group">\n <div class="col-md-12">\n <p>\n To modify min and max instance counts, use the\n <a href ng-click="$ctrl.command.advancedMode = true">Advanced Mode</a>.\n </p>\n </div>\n </div>\n <div class="form-group form-inline">\n <div class="col-md-3 sm-label-right">Current size</div>\n <div class="col-md-6">\n <input\n type="number"\n class="form-control input-sm"\n ng-model="$ctrl.currentSize.desired"\n style="width: 60px"\n readonly\n />\n instance<span ng-if="$ctrl.currentSize.desired > 1">s</span>\n </div>\n </div>\n <div class="form-group form-inline">\n <div class="col-md-3 sm-label-right">Resize to</div>\n <div class="col-md-6">\n <input\n type="number"\n class="form-control input-sm highlight-pristine"\n ng-model="$ctrl.command.newSize"\n min="0"\n required\n style="width: 60px"\n />\n instances\n </div>\n </div>\n</div>\n')}]);const vt="spinnaker.ecs.serverGroup.details.resize.controller";e.module(vt,[N,gt]).controller("ecsResizeServerGroupCtrl",["$scope","$uibModalInstance","serverGroupWriter","application","serverGroup",function(t,n,a,r,i){t.serverGroup=i,t.currentSize={min:i.capacity.min,max:i.capacity.max,desired:i.capacity.desired,newSize:null},t.verification={},t.command=e.copy(t.currentSize),t.command.advancedMode=i.capacity.min!==i.capacity.max,r&&r.attributes&&(r.attributes.platformHealthOnlyShowOverride&&r.attributes.platformHealthOnly&&(t.command.interestingHealthProviderNames=["Ecs"]),t.command.platformHealthOnlyShowOverride=r.attributes.platformHealthOnlyShowOverride),this.isValid=function(){const e=t.command;return!!t.verification.verified&&(e.advancedMode?e.min<=e.max&&e.desired>=e.min&&e.desired<=e.max:null!==e.newSize)},t.taskMonitor=new z({application:r,title:"Resizing "+i.name,modalInstance:n}),this.resize=function(){if(!this.isValid())return;let e={min:t.command.min,max:t.command.max,desired:t.command.desired};t.command.advancedMode||(e={min:t.command.newSize,max:t.command.newSize,desired:t.command.newSize});t.taskMonitor.submit(function(){return a.resizeServerGroup(i,r,{capacity:e,interestingHealthProviderNames:t.command.interestingHealthProviderNames,reason:t.command.reason})})},this.cancel=function(){n.dismiss()}}]);const ht="spinnaker.ecs.serverGroup.details.rollback.controller";t(ht,[N]).controller("ecsRollbackServerGroupCtrl",["$scope","$uibModalInstance","serverGroupWriter","application","serverGroup","disabledServerGroups","allServerGroups",function(e,t,n,a,r,i,s){e.serverGroup=r,e.disabledServerGroups=i.sort((e,t)=>t.name.localeCompare(e.name)),e.allServerGroups=s.sort((e,t)=>t.name.localeCompare(e.name)),e.verification={},e.command={rollbackType:"EXPLICIT",rollbackContext:{rollbackServerGroupName:r.name}},a&&a.attributes&&(a.attributes.platformHealthOnlyShowOverride&&a.attributes.platformHealthOnly&&(e.command.interestingHealthProviderNames=["Ecs"]),e.command.platformHealthOnlyShowOverride=a.attributes.platformHealthOnlyShowOverride),this.isValid=function(){const t=e.command;return!!e.verification.verified&&void 0!==t.rollbackContext.restoreServerGroupName},e.taskMonitor=new z({application:a,title:"Rollback "+r.name,modalInstance:t}),this.rollback=function(){if(!this.isValid())return;e.taskMonitor.submit(function(){return n.rollbackServerGroup(r,a,e.command)})},this.cancel=function(){t.dismiss()},this.label=function(e){return e?e.buildInfo&&e.buildInfo.jenkins&&e.buildInfo.jenkins.number?e.name+" (build #"+e.buildInfo.jenkins.number+")":e.name:""},this.group=function(e){return e.isDisabled?"Disabled Server Groups":"Enabled Server Groups"}}]);const ft="spinnaker.ecs.serverGroup.transformer";t(ft,[]).service("ecsServerGroupTransformer",class{addComparator(e){if(e.comparisonOperator)switch(e.comparisonOperator){case"LessThanThreshold":e.comparator="<";break;case"GreaterThanThreshold":e.comparator=">";break;case"LessThanOrEqualToThreshold":e.comparator="≤";break;case"GreaterThanOrEqualToThreshold":e.comparator="≥"}}addAdjustmentAttributes(e){e.operator=e.scalingAdjustment<0?"decrease":"increase",e.absAdjustment=Math.abs(e.scalingAdjustment)}transformScalingPolicy(e){const t={...e},n=(e,t)=>t.metricIntervalUpperBound-e.metricIntervalUpperBound,a=(e,t)=>e.metricIntervalLowerBound-t.metricIntervalLowerBound;if(t.alarms=e.alarms||[],t.alarms.forEach(e=>this.addComparator(e)),this.addAdjustmentAttributes(t),t.stepAdjustments&&t.stepAdjustments.length){t.stepAdjustments.forEach(e=>this.addAdjustmentAttributes(e));const r=e.stepAdjustments.every(e=>void 0!==e.metricIntervalUpperBound)?n:a;t.stepAdjustments.sort((e,t)=>r(e,t))}return t}normalizeServerGroupDetails(e){const t={...e};return e.scalingPolicies&&(t.scalingPolicies=e.scalingPolicies.map(e=>this.transformScalingPolicy(e))),t}normalizeServerGroup(e){return e.instances.forEach(t=>{t.vpcId=e.vpcId}),de.listVpcs().then(t=>this.addVpcNameToServerGroup(e)(t))}addVpcNameToServerGroup(e){return t=>{const n=t.find(t=>t.id===e.vpcId);return e.vpcName=n?n.name:"",e}}convertServerGroupCommandToDeployConfiguration(e){const t=ie({backingData:[],viewState:[]},e);return t.cloudProvider="ecs",t.availabilityZones={},t.availabilityZones[t.region]=e.availabilityZones,t.loadBalancers=(e.loadBalancers||[]).concat(e.vpcLoadBalancers||[]),t.targetGroup=e.targetGroup||"",t.account=t.credentials,t.subnetType=t.subnetType||"","clone"!==e.viewState.mode&&delete t.source,delete t.region,delete t.viewState,delete t.backingData,delete t.selectedProvider,delete t.instanceProfile,delete t.vpcId,t}});const yt="spinnaker.ecs.serverGroup.details.controller";e.module(yt,[V,ft,P,N,Xe,vt,ht]).controller("ecsServerGroupDetailsCtrl",["$scope","$state","app","serverGroup","ecsServerGroupCommandBuilder","$uibModal","serverGroupWriter","ecsServerGroupTransformer","overrideRegistry",function(t,n,a,r,i,o,l,c,d){this.state={loading:!0},this.firewallsLabel=C.get("Firewalls"),this.application=a;const p=()=>{t.$$destroyed||n.go("^",{allowModalToStayOpen:!0},{location:"replace"})},u=()=>{this.state.loading=!1},m=()=>a.ready().then(()=>{let e=Q(a.serverGroups.data,e=>e.name===r.name&&e.account===r.accountId&&e.region===r.region);return e||a.loadBalancers.data.some(t=>{if(t.account===r.accountId&&t.region===r.region)return t.serverGroups.some(t=>{if(t.name===r.name)return e=t,!0})}),e}).then(t=>q.getServerGroup(a.name,r.accountId,r.region,r.name).then(n=>{if(u(),e.extend(n,t,{account:r.accountId}),this.serverGroup=c.normalizeServerGroupDetails(n),this.applyAccountDetails(this.serverGroup),oe(this.serverGroup))p();else{this.image=n.image?n.image:void 0;const e=this.serverGroup.asg?this.serverGroup.asg.vpczoneIdentifier:"";if(""!==e){const t=e.split(",")[0];G.listSubnets().then(e=>{const n=X(e).find({id:t}).value();this.serverGroup.subnetType=n.purpose})}if(n.image&&n.image.description){n.image.description.split(", ").forEach(e=>{const t=e.split("=");2===t.length&&"ancestor_name"===t[0]&&(n.image.baseImage=t[1])})}if(n.image&&n.image.tags){const e=n.image.tags.find(e=>"base_ami_version"===e.key);e&&(n.baseAmiVersion=e.value)}this.scalingPolicies=this.serverGroup.scalingPolicies,K(this.serverGroup,"buildInfo.jenkins")&&(this.changeConfig.buildInfo={jenkins:this.serverGroup.buildInfo.jenkins})}})).catch(p);m().then(()=>{t.$$destroyed||a.serverGroups.onRefresh(t,m)}),this.destroyServerGroup=()=>{const e=this.serverGroup,t={application:a,title:"Destroying "+e.name,onTaskComplete:()=>{n.includes("**.serverGroup",r)&&n.go("^")}},r={name:e.name,accountId:e.account,region:e.region},i={header:"Really destroy "+e.name+"?",buttonText:"Destroy "+e.name,account:e.account,taskMonitorConfig:t,submitMethod:t=>l.destroyServerGroup(e,a,t),askForReason:!0,platformHealthOnlyShowOverride:a.attributes.platformHealthOnlyShowOverride,platformHealthType:"Ecs"};U.addDestroyWarningMessage(a,e,i),a.attributes.platformHealthOnlyShowOverride&&a.attributes.platformHealthOnly&&(i.interestingHealthProviderNames=["Ecs"]),s.confirm(i)},this.disableServerGroup=()=>{const e=this.serverGroup,t={application:a,title:"Disabling "+e.name},n={header:"Really disable "+e.name+"?",buttonText:"Disable "+e.name,account:e.account,taskMonitorConfig:t,platformHealthOnlyShowOverride:a.attributes.platformHealthOnlyShowOverride,platformHealthType:"Ecs",submitMethod:t=>l.disableServerGroup(e,a,t),askForReason:!0};U.addDisableWarningMessage(a,e,n),a.attributes.platformHealthOnlyShowOverride&&a.attributes.platformHealthOnly&&(n.interestingHealthProviderNames=["Ecs"]),s.confirm(n)},this.enableServerGroup=()=>{const e=this.serverGroup,t={application:a,title:"Enabling "+e.name},n={header:"Really enable "+e.name+"?",buttonText:"Enable "+e.name,account:e.account,taskMonitorConfig:t,platformHealthOnlyShowOverride:a.attributes.platformHealthOnlyShowOverride,platformHealthType:"Ecs",submitMethod:t=>l.enableServerGroup(e,a,t),askForReason:!0};a.attributes.platformHealthOnlyShowOverride&&a.attributes.platformHealthOnly&&(n.interestingHealthProviderNames=["Ecs"]),s.confirm(n)},this.rollbackServerGroup=()=>{o.open({templateUrl:d.getTemplate("ecs.rollback.modal","ecs/src/serverGroup/details/rollback/rollbackServerGroup.html"),windowClass:"modal-z-index",controller:"ecsRollbackServerGroupCtrl as ctrl",resolve:{serverGroup:()=>this.serverGroup,disabledServerGroups:()=>{const e=Q(a.clusters,{name:this.serverGroup.cluster,account:this.serverGroup.account});return se(e.serverGroups,{isDisabled:!0,region:this.serverGroup.region})},allServerGroups:()=>a.getDataSource("serverGroups").data.filter(e=>e.cluster===this.serverGroup.cluster&&e.region===this.serverGroup.region&&e.account===this.serverGroup.account&&e.name!==this.serverGroup.name),application:()=>a}})},this.resizeServerGroup=()=>{o.open({templateUrl:d.getTemplate("ecs.resize.modal","ecs/src/serverGroup/details/resize/resizeServerGroup.html"),controller:"ecsResizeServerGroupCtrl as ctrl",windowClass:"modal-z-index",resolve:{serverGroup:()=>this.serverGroup,application:()=>a}})},this.cloneServerGroup=e=>{o.open({templateUrl:"ecs/src/serverGroup/configure/wizard/serverGroupWizard.html",controller:"ecsCloneServerGroupCtrl as ctrl",size:"lg",windowClass:"modal-z-index",resolve:{title:()=>"Clone "+e.name,application:()=>a,serverGroupCommand:()=>i.buildServerGroupCommandFromExisting(a,e)}})},this.buildJenkinsLink=()=>{if(K(this,"serverGroup.buildInfo.buildInfoUrl"))return this.serverGroup.buildInfo.buildInfoUrl;if(K(this,"serverGroup.buildInfo.jenkins")){const e=this.serverGroup.buildInfo.jenkins;return e.host+"job/"+e.name+"/"+e.number}return null},this.truncateCommitHash=()=>this.serverGroup&&this.serverGroup.buildInfo&&this.serverGroup.buildInfo.commit?this.serverGroup.buildInfo.commit.substring(0,8):null,this.applyAccountDetails=e=>f.getAccountDetails(e.account).then(t=>{e.accountDetails=t})}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/serverGroup/details/rollback/rollbackServerGroup.html",'<div modal-page class="confirmation-modal">\n <task-monitor monitor="taskMonitor"></task-monitor>\n <form role="form">\n <modal-close dismiss="$dismiss()"></modal-close>\n <div class="modal-header">\n <h4 class="modal-title">Rollback {{serverGroup.name}}</h4>\n </div>\n <div class="modal-body confirmation-modal">\n <div class="row">\n <div class="col-sm-3 sm-label-right">Restore to</div>\n <div class="col-sm-6">\n <ui-select ng-model="command.rollbackContext.restoreServerGroupName" class="form-control input-sm">\n <ui-select-match placeholder="Select...">{{ctrl.label($select.selected)}}</ui-select-match>\n <ui-select-choices group-by="ctrl.group" repeat="serverGroup.name as serverGroup in allServerGroups">\n <span ng-bind-html="ctrl.label(serverGroup)"></span>\n </ui-select-choices>\n </ui-select>\n </div>\n </div>\n\n <div class="row" ng-if="command.platformHealthOnlyShowOverride">\n <div class="col-sm-10 col-sm-offset-1">\n <platform-health-override\n command="command"\n platform-health-type="\'Ecs\'"\n show-help-details="true"\n field-columns="12"\n >\n </platform-health-override>\n </div>\n </div>\n\n <task-reason command="command"></task-reason>\n\n <div class="row">\n <div class="col-sm-4 sm-label-right">Rollback Operations</div>\n </div>\n <div class="row">\n <div class="col-sm-11 col-sm-offset-1">\n <ol>\n <li>Enable <em>{{ command.rollbackContext.restoreServerGroupName || \'previous server group\' }}</em></li>\n <li>\n Resize <em>{{ command.rollbackContext.restoreServerGroupName || \'previous server group\' }}</em> to [\n <strong>min</strong>: {{serverGroup.capacity.desired}}, <strong>max</strong>: {{ serverGroup.capacity.max\n }}, <strong>desired</strong>: {{ serverGroup.capacity.desired }} ]<br />(minimum capacity pinned at\n {{serverGroup.capacity.desired}} to prevent autoscaling down during rollback)\n </li>\n <li>Disable {{ serverGroup.name }}</li>\n <li>\n Restore minimum capacity of\n <em>{{ command.rollbackContext.restoreServerGroupName || \'previous server group\' }}</em> [\n <strong>min</strong>: {{ serverGroup.capacity.min }} ]\n </li>\n </ol>\n <p>This rollback will affect server groups in {{ serverGroup.account }} ({{ serverGroup.region }}).</p>\n </div>\n </div>\n </div>\n <ecs-footer\n action="ctrl.rollback()"\n cancel="ctrl.cancel()"\n is-valid="ctrl.isValid()"\n account="serverGroup.account"\n verification="verification"\n ></ecs-footer>\n </form>\n</div>\n')}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/serverGroup/details/resize/resizeServerGroup.html",'<div modal-page class="confirmation-modal">\n <task-monitor monitor="taskMonitor"></task-monitor>\n <form role="form">\n <modal-close dismiss="$dismiss()"></modal-close>\n <div class="modal-header">\n <h4 class="modal-title">Resize {{serverGroup.name}}</h4>\n </div>\n <div class="modal-body confirmation-modal">\n <div class="form-horizontal">\n <ecs-resize-capacity command="command" current-size="currentSize"></ecs-resize-capacity>\n </div>\n <div class="row" ng-if="command.platformHealthOnlyShowOverride">\n <div class="col-sm-10 col-sm-offset-1">\n <platform-health-override command="command" platform-health-type="\'Ecs\'" show-help-details="true">\n </platform-health-override>\n </div>\n </div>\n <task-reason command="command"></task-reason>\n </div>\n <ecs-footer\n action="ctrl.resize()"\n cancel="ctrl.cancel()"\n is-valid="ctrl.isValid()"\n account="serverGroup.account"\n verification="verification"\n ></ecs-footer>\n </form>\n</div>\n')}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/serverGroup/configure/wizard/serverGroupWizard.html",'<form name="form" class="form-horizontal" novalidate>\n <div ng-if="state.requiresTemplateSelection">\n <ng-include src="pages.templateSelection"></ng-include>\n </div>\n <div ng-if="!state.loaded" style="height: 200px">\n <h3 us-spinner="{radius:30, width:8, length: 16}"></h3>\n </div>\n <div ng-if="!state.requiresTemplateSelection">\n <v2-modal-wizard ng-show="state.loaded" heading="{{title}}" task-monitor="taskMonitor" dismiss="$dismiss()">\n <v2-wizard-page key="basicSettings" label="Basic Settings" mark-complete-on-view="false" done="true">\n <ng-include src="pages.basicSettings"></ng-include>\n </v2-wizard-page>\n <v2-wizard-page key="networking" label="Networking" done="true">\n <ng-include src="pages.networking"></ng-include>\n </v2-wizard-page>\n <v2-wizard-page key="taskDefinition" label="Task Definition" done="true">\n <ng-include src="pages.taskDefinition"></ng-include>\n </v2-wizard-page>\n <div ng-if="!command.useTaskDefinitionArtifact">\n <v2-wizard-page key="container" label="Container" done="true">\n <ng-include src="pages.container"></ng-include>\n </v2-wizard-page>\n </div>\n <v2-wizard-page key="horizontalScaling" label="Horizontal Scaling" done="true">\n <ng-include src="pages.horizontalScaling"></ng-include>\n </v2-wizard-page>\n <div ng-if="!command.useTaskDefinitionArtifact">\n <v2-wizard-page key="logging" label="Logging" done="true">\n <ng-include src="pages.logging"></ng-include>\n </v2-wizard-page>\n </div>\n <v2-wizard-page key="serviceDiscovery" label="Service Discovery" done="true">\n <ng-include ng-if="!command.useTaskDefinitionArtifact" src="pages.serviceDiscovery"></ng-include>\n <ng-include ng-if="command.useTaskDefinitionArtifact" src="pages.serviceDiscovery"></ng-include>\n </v2-wizard-page>\n <v2-wizard-page key="advanced" label="Advanced Settings" mark-complete-on-view="false" done="true">\n <ng-include src="pages.advancedSettings"></ng-include>\n </v2-wizard-page>\n </v2-modal-wizard>\n <div class="modal-footer" ng-if="state.loaded">\n <button ng-disabled="taskMonitor.submitting" class="btn btn-default btn-cancel" ng-click="ctrl.cancel()">\n Cancel\n </button>\n <submit-button\n data-test-id="ServerGroupWizard.submitButton"\n ng-if="ctrl.showSubmitButton()"\n is-disabled="!ctrl.isValid() || taskMonitor.submitting"\n label="command.viewState.submitButtonLabel"\n submitting="taskMonitor.submitting"\n on-click="ctrl.submit()"\n is-new="true"\n ></submit-button>\n </div>\n </div>\n</form>\n')}]);const bt="spinnaker.ecs.serverGroup.details";t(bt,[yt]);class St{static getEvents(e){return r("/applications").path(e.app,"serverGroups",e.account,e.name,"events").query({region:e.region,provider:e.cloudProvider}).get().catch(e=>(ye.error(e,"error retrieving events"),[]))}}class kt{constructor(e,t){this.$uibModalInstance=e,this.serverGroup=t,this.events=[]}$onInit(){this.viewState={loading:!0,error:!1},St.getEvents(this.serverGroup).then(e=>{this.viewState.loading=!1,this.events=e},()=>{this.viewState.error=!0})}close(){this.$uibModalInstance.close()}}kt.$inject=["$uibModalInstance","serverGroup"];const Ct="spinnaker.ecs.serverGroup.events.controller";t(Ct,[]).controller("EventsController",kt);class wt{constructor(e){this.$uibModal=e}showEvents(){this.$uibModal.open({templateUrl:"ecs/src/serverGroup/events/events.html",controller:kt,controllerAs:"$ctrl",windowClass:"modal-z-index",resolve:{serverGroup:()=>this.serverGroup}})}}wt.$inject=["$uibModal"];const Et={bindings:{serverGroup:"<"},controller:wt,template:'<a href ng-click="$ctrl.showEvents()">View Events</a>'},Dt="spinnaker.ecs.serverGroup.details.viewEvents.link";t(Dt,[Ct]).component("viewEventsLink",Et),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/serverGroup/events/events.html",'<div modal-page>\n <modal-close dismiss="$ctrl.close()"></modal-close>\n <div class="modal-header">\n <h4 class="modal-title">Server Group Events for {{$ctrl.serverGroup.name}}</h4>\n </div>\n <div class="modal-body">\n <div class="loading" ng-if="$ctrl.viewState.loading">\n <loading-spinner size="\'small\'"></loading-spinner>\n </div>\n <div ng-if="$ctrl.viewState.error" class="text-center">\n <p>There was an error loading events for {{$ctrl.serverGroup.name}}. Please try again later.</p>\n </div>\n <div ng-if="!$ctrl.viewState.loading && !$ctrl.viewState.error && !$ctrl.events.length" class="text-center">\n <p>No scaling events found for {{$ctrl.serverGroup.name}}.</p>\n </div>\n\n <div ng-repeat="event in $ctrl.events" ng-if="!$ctrl.viewState.loading">\n <p class="clearfix"></p>\n <div ng-if="event.status === \'Success\'">\n <span class="label label-success pull-left">{{event.status}}</span>\n </div>\n <div ng-if="event.status !== \'Success\'">\n <span class="label label-{{event.status === \'Transition\' ? \'info\' : \'danger\'}} pull-left"\n >{{event.status}}</span\n >\n </div>\n\n <span class="label label-default pull-right">{{event.createdAt | timestamp}}</span>\n <div>{{event.message}}</div>\n <hr ng-if="!$last" />\n </div>\n </div>\n <div class="modal-footer">\n <button class="btn btn-primary" ng-click="$ctrl.close()">Close</button>\n </div>\n</div>\n')}]);const Gt="spinnaker.ecs.serverGroup";t(Gt,[Dt]);!function(e,t){void 0===t&&(t={});var n=t.insertAt;if("undefined"!=typeof document){var a=document.head||document.getElementsByTagName("head")[0],r=document.createElement("style");r.type="text/css","top"===n&&a.firstChild?a.insertBefore(r,a.firstChild):a.appendChild(r),r.styleSheet?r.styleSheet.cssText=e:r.appendChild(document.createTextNode(e))}}('.cloud-provider-logo .icon-ecs {\n -webkit-mask-image: url("data:image/svg+xml,%3Csvg id%3D%22Layer_1%22 data-name%3D%22Layer 1%22 xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22 width%3D%22100%22 height%3D%22100%22 viewBox%3D%220 0 100 100%22%3E %3Ctitle%3ECompute%3C%2Ftitle%3E %3Cg%3E %3Cpolygon points%3D%2219.64 22.51 16 24.32 16 75.68 19.64 77.49 33.98 51.07 19.64 22.51%22 fill%3D%22%239d5025%22%2F%3E %3Cpolygon points%3D%2230.72 31.78 36.08 24.19 60.1 34.87 54.5 35.76 30.72 31.78%22 fill%3D%22%239d5025%22%2F%3E %3Cpolygon points%3D%2226.56 68.77 32.46 76.88 60.1 64.95 54.76 64.12 26.56 68.77%22 fill%3D%22%239d5025%22%2F%3E %3Cpolygon points%3D%2228.12 75.5 19.64 77.49 19.64 22.51 28.12 24.44 28.12 75.5%22 fill%3D%22%23f58536%22%2F%3E %3Cpolygon points%3D%2223.66 20.5 28.12 18.27 36.52 53.56 28.12 81.73 23.66 79.5 23.66 20.5%22 fill%3D%22%239d5025%22%2F%3E %3Cpolygon points%3D%2254.46 64.08 60.1 64.95 65.26 50.58 60.1 34.87 54.46 35.76 54.46 64.08%22 fill%3D%22%239d5025%22%2F%3E %3Cpolygon points%3D%2236.8 79.28 28.12 81.73 28.12 18.27 36.8 20.73 36.8 79.28%22 fill%3D%22%23f58536%22%2F%3E %3Cpolygon points%3D%2266.01 63.84 28.12 70.88 28.12 81.73 66.01 71.03 66.01 63.84%22 fill%3D%22%23f58536%22%2F%3E %3Cpolygon points%3D%2266.08 36 28.12 28.79 28.12 18.27 66.08 29.04 66.08 36%22 fill%3D%22%23f58536%22%2F%3E %3Cpolygon points%3D%2260.1 27.34 66.19 29.02 66.19 71.03 60.1 72.7 60.1 27.34%22 fill%3D%22%23f58536%22%2F%3E %3Cpolygon points%3D%2284 44.45 67.7 45.22 61.94 44.83 78.42 31.55 84 44.45%22 fill%3D%22%236b3a19%22%2F%3E %3Cpolygon points%3D%2261.94 44.83 78.42 43.9 78.42 31.55 61.94 34.22 61.94 44.83%22 fill%3D%22%239d5025%22%2F%3E %3Cpolygon points%3D%2246.43 43.79 63.13 26.96 71.62 43.22 54.31 44.32 46.43 43.79%22 fill%3D%22%236b3a19%22%2F%3E %3Cpolygon points%3D%2246.43 43.79 63.13 42.37 63.13 26.96 46.43 30.87 46.43 43.79%22 fill%3D%22%239d5025%22%2F%3E %3Cpolygon points%3D%2261.94 55.39 84 55.77 78.42 68.67 61.94 66 61.94 55.39%22 fill%3D%22%239d5025%22%2F%3E %3Cpolygon points%3D%2246.43 56.43 71.62 57.01 63.13 73.26 46.43 69.36 46.43 56.43%22 fill%3D%22%239d5025%22%2F%3E %3Cpolygon points%3D%2246.43 56.43 63.13 57.86 71.62 57.01 54.31 55.9 46.43 56.43%22 fill%3D%22%23fbbf93%22%2F%3E %3Cpolygon points%3D%2284 55.77 67.7 55.01 61.94 55.39 78.42 56.33 84 55.77%22 fill%3D%22%23fbbf93%22%2F%3E %3Cpolygon points%3D%2278.42 43.9 84 44.45 84 33.22 78.42 31.55 78.42 43.9%22 fill%3D%22%23f58536%22%2F%3E %3Cpolygon points%3D%2271.62 43.22 63.13 42.37 63.13 26.96 71.62 29.51 71.62 43.22%22 fill%3D%22%23f58536%22%2F%3E %3Cpolygon points%3D%2278.42 56.33 84 55.77 84 67 78.42 68.67 78.42 56.33%22 fill%3D%22%23f58536%22%2F%3E %3Cpolygon points%3D%2271.62 57.01 63.13 57.86 63.13 73.26 71.62 70.72 71.62 57.01%22 fill%3D%22%23f58536%22%2F%3E %3C%2Fg%3E%3C%2Fsvg%3E");\n mask-image: url("data:image/svg+xml,%3Csvg id%3D%22Layer_1%22 data-name%3D%22Layer 1%22 xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22 width%3D%22100%22 height%3D%22100%22 viewBox%3D%220 0 100 100%22%3E %3Ctitle%3ECompute%3C%2Ftitle%3E %3Cg%3E %3Cpolygon points%3D%2219.64 22.51 16 24.32 16 75.68 19.64 77.49 33.98 51.07 19.64 22.51%22 fill%3D%22%239d5025%22%2F%3E %3Cpolygon points%3D%2230.72 31.78 36.08 24.19 60.1 34.87 54.5 35.76 30.72 31.78%22 fill%3D%22%239d5025%22%2F%3E %3Cpolygon points%3D%2226.56 68.77 32.46 76.88 60.1 64.95 54.76 64.12 26.56 68.77%22 fill%3D%22%239d5025%22%2F%3E %3Cpolygon points%3D%2228.12 75.5 19.64 77.49 19.64 22.51 28.12 24.44 28.12 75.5%22 fill%3D%22%23f58536%22%2F%3E %3Cpolygon points%3D%2223.66 20.5 28.12 18.27 36.52 53.56 28.12 81.73 23.66 79.5 23.66 20.5%22 fill%3D%22%239d5025%22%2F%3E %3Cpolygon points%3D%2254.46 64.08 60.1 64.95 65.26 50.58 60.1 34.87 54.46 35.76 54.46 64.08%22 fill%3D%22%239d5025%22%2F%3E %3Cpolygon points%3D%2236.8 79.28 28.12 81.73 28.12 18.27 36.8 20.73 36.8 79.28%22 fill%3D%22%23f58536%22%2F%3E %3Cpolygon points%3D%2266.01 63.84 28.12 70.88 28.12 81.73 66.01 71.03 66.01 63.84%22 fill%3D%22%23f58536%22%2F%3E %3Cpolygon points%3D%2266.08 36 28.12 28.79 28.12 18.27 66.08 29.04 66.08 36%22 fill%3D%22%23f58536%22%2F%3E %3Cpolygon points%3D%2260.1 27.34 66.19 29.02 66.19 71.03 60.1 72.7 60.1 27.34%22 fill%3D%22%23f58536%22%2F%3E %3Cpolygon points%3D%2284 44.45 67.7 45.22 61.94 44.83 78.42 31.55 84 44.45%22 fill%3D%22%236b3a19%22%2F%3E %3Cpolygon points%3D%2261.94 44.83 78.42 43.9 78.42 31.55 61.94 34.22 61.94 44.83%22 fill%3D%22%239d5025%22%2F%3E %3Cpolygon points%3D%2246.43 43.79 63.13 26.96 71.62 43.22 54.31 44.32 46.43 43.79%22 fill%3D%22%236b3a19%22%2F%3E %3Cpolygon points%3D%2246.43 43.79 63.13 42.37 63.13 26.96 46.43 30.87 46.43 43.79%22 fill%3D%22%239d5025%22%2F%3E %3Cpolygon points%3D%2261.94 55.39 84 55.77 78.42 68.67 61.94 66 61.94 55.39%22 fill%3D%22%239d5025%22%2F%3E %3Cpolygon points%3D%2246.43 56.43 71.62 57.01 63.13 73.26 46.43 69.36 46.43 56.43%22 fill%3D%22%239d5025%22%2F%3E %3Cpolygon points%3D%2246.43 56.43 63.13 57.86 71.62 57.01 54.31 55.9 46.43 56.43%22 fill%3D%22%23fbbf93%22%2F%3E %3Cpolygon points%3D%2284 55.77 67.7 55.01 61.94 55.39 78.42 56.33 84 55.77%22 fill%3D%22%23fbbf93%22%2F%3E %3Cpolygon points%3D%2278.42 43.9 84 44.45 84 33.22 78.42 31.55 78.42 43.9%22 fill%3D%22%23f58536%22%2F%3E %3Cpolygon points%3D%2271.62 43.22 63.13 42.37 63.13 26.96 71.62 29.51 71.62 43.22%22 fill%3D%22%23f58536%22%2F%3E %3Cpolygon points%3D%2278.42 56.33 84 55.77 84 67 78.42 68.67 78.42 56.33%22 fill%3D%22%23f58536%22%2F%3E %3Cpolygon points%3D%2271.62 57.01 63.13 57.86 63.13 73.26 71.62 70.72 71.62 57.01%22 fill%3D%22%23f58536%22%2F%3E %3C%2Fg%3E%3C%2Fsvg%3E");\n}\n');const At="spinnaker.ecs";t(At,[Qe,bt,De,ft,et,it,mt,rt,ct,pt,nt,ot,Ee,Ve,Me,He,ke,st,Xe,Ge,Le,Re,$e,Be,Fe,Oe,Ue,qe,Ze,Gt,xe]).config(function(){i.registerProvider("ecs",{name:"EC2 Container Service",logo:{path:"data:image/svg+xml,%3Csvg%20id%3D%22Layer_1%22%20data-name%3D%22Layer%201%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22100%22%20height%3D%22100%22%20viewBox%3D%220%200%20100%20100%22%3E%20%20%3Ctitle%3ECompute%3C%2Ftitle%3E%20%20%3Cg%3E%20%20%20%20%3Cpolygon%20points%3D%2219.64%2022.51%2016%2024.32%2016%2075.68%2019.64%2077.49%2033.98%2051.07%2019.64%2022.51%22%20fill%3D%22%239d5025%22%2F%3E%20%20%20%20%3Cpolygon%20points%3D%2230.72%2031.78%2036.08%2024.19%2060.1%2034.87%2054.5%2035.76%2030.72%2031.78%22%20fill%3D%22%239d5025%22%2F%3E%20%20%20%20%3Cpolygon%20points%3D%2226.56%2068.77%2032.46%2076.88%2060.1%2064.95%2054.76%2064.12%2026.56%2068.77%22%20fill%3D%22%239d5025%22%2F%3E%20%20%20%20%3Cpolygon%20points%3D%2228.12%2075.5%2019.64%2077.49%2019.64%2022.51%2028.12%2024.44%2028.12%2075.5%22%20fill%3D%22%23f58536%22%2F%3E%20%20%20%20%3Cpolygon%20points%3D%2223.66%2020.5%2028.12%2018.27%2036.52%2053.56%2028.12%2081.73%2023.66%2079.5%2023.66%2020.5%22%20fill%3D%22%239d5025%22%2F%3E%20%20%20%20%3Cpolygon%20points%3D%2254.46%2064.08%2060.1%2064.95%2065.26%2050.58%2060.1%2034.87%2054.46%2035.76%2054.46%2064.08%22%20fill%3D%22%239d5025%22%2F%3E%20%20%20%20%3Cpolygon%20points%3D%2236.8%2079.28%2028.12%2081.73%2028.12%2018.27%2036.8%2020.73%2036.8%2079.28%22%20fill%3D%22%23f58536%22%2F%3E%20%20%20%20%3Cpolygon%20points%3D%2266.01%2063.84%2028.12%2070.88%2028.12%2081.73%2066.01%2071.03%2066.01%2063.84%22%20fill%3D%22%23f58536%22%2F%3E%20%20%20%20%3Cpolygon%20points%3D%2266.08%2036%2028.12%2028.79%2028.12%2018.27%2066.08%2029.04%2066.08%2036%22%20fill%3D%22%23f58536%22%2F%3E%20%20%20%20%3Cpolygon%20points%3D%2260.1%2027.34%2066.19%2029.02%2066.19%2071.03%2060.1%2072.7%2060.1%2027.34%22%20fill%3D%22%23f58536%22%2F%3E%20%20%20%20%3Cpolygon%20points%3D%2284%2044.45%2067.7%2045.22%2061.94%2044.83%2078.42%2031.55%2084%2044.45%22%20fill%3D%22%236b3a19%22%2F%3E%20%20%20%20%3Cpolygon%20points%3D%2261.94%2044.83%2078.42%2043.9%2078.42%2031.55%2061.94%2034.22%2061.94%2044.83%22%20fill%3D%22%239d5025%22%2F%3E%20%20%20%20%3Cpolygon%20points%3D%2246.43%2043.79%2063.13%2026.96%2071.62%2043.22%2054.31%2044.32%2046.43%2043.79%22%20fill%3D%22%236b3a19%22%2F%3E%20%20%20%20%3Cpolygon%20points%3D%2246.43%2043.79%2063.13%2042.37%2063.13%2026.96%2046.43%2030.87%2046.43%2043.79%22%20fill%3D%22%239d5025%22%2F%3E%20%20%20%20%3Cpolygon%20points%3D%2261.94%2055.39%2084%2055.77%2078.42%2068.67%2061.94%2066%2061.94%2055.39%22%20fill%3D%22%239d5025%22%2F%3E%20%20%20%20%3Cpolygon%20points%3D%2246.43%2056.43%2071.62%2057.01%2063.13%2073.26%2046.43%2069.36%2046.43%2056.43%22%20fill%3D%22%239d5025%22%2F%3E%20%20%20%20%3Cpolygon%20points%3D%2246.43%2056.43%2063.13%2057.86%2071.62%2057.01%2054.31%2055.9%2046.43%2056.43%22%20fill%3D%22%23fbbf93%22%2F%3E%20%20%20%20%3Cpolygon%20points%3D%2284%2055.77%2067.7%2055.01%2061.94%2055.39%2078.42%2056.33%2084%2055.77%22%20fill%3D%22%23fbbf93%22%2F%3E%20%20%20%20%3Cpolygon%20points%3D%2278.42%2043.9%2084%2044.45%2084%2033.22%2078.42%2031.55%2078.42%2043.9%22%20fill%3D%22%23f58536%22%2F%3E%20%20%20%20%3Cpolygon%20points%3D%2271.62%2043.22%2063.13%2042.37%2063.13%2026.96%2071.62%2029.51%2071.62%2043.22%22%20fill%3D%22%23f58536%22%2F%3E%20%20%20%20%3Cpolygon%20points%3D%2278.42%2056.33%2084%2055.77%2084%2067%2078.42%2068.67%2078.42%2056.33%22%20fill%3D%22%23f58536%22%2F%3E%20%20%20%20%3Cpolygon%20points%3D%2271.62%2057.01%2063.13%2057.86%2063.13%2073.26%2071.62%2070.72%2071.62%2057.01%22%20fill%3D%22%23f58536%22%2F%3E%20%20%3C%2Fg%3E%3C%2Fsvg%3E"},serverGroup:{transformer:"ecsServerGroupTransformer",detailsTemplateUrl:"ecs/src/serverGroup/details/serverGroupDetails.html",detailsController:"ecsServerGroupDetailsCtrl",cloneServerGroupTemplateUrl:"ecs/src/serverGroup/configure/wizard/serverGroupWizard.html",cloneServerGroupController:"ecsCloneServerGroupCtrl",commandBuilder:"ecsServerGroupCommandBuilder",scalingActivitiesEnabled:!1,skipUpstreamStageCheck:!0},loadBalancer:{transformer:ze,ClusterContainer:Te,targetGroupDetails:Ie,details:Pe},instance:{detailsTemplateUrl:"ecs/src/instance/details/instanceDetails.html",detailsController:"ecsInstanceDetailsCtrl"},securityGroup:{transformer:"ecsSecurityGroupTransformer",reader:"ecsSecurityGroupReader",detailsTemplateUrl:"ecs/src/securityGroup/details/securityGroupDetail.html",detailsController:"ecsSecurityGroupDetailsCtrl"}})}),H.registerProvider("ecs",["redblack"]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/serverGroup/details/serverGroupDetails.html",'<div class="details-panel" ng-class="{ disabled: ctrl.serverGroup.isDisabled }">\n <div class="header" ng-if="ctrl.state.loading">\n <div class="close-button">\n <a class="btn btn-link" ui-sref="^">\n <span class="glyphicon glyphicon-remove"></span>\n </a>\n </div>\n <h4 class="text-center">\n <span us-spinner="{radius:20, width:6, length: 12}"></span>\n </h4>\n </div>\n\n <div class="header" ng-if="!ctrl.state.loading">\n <div class="close-button">\n <a class="btn btn-link" ui-sref="^">\n <span class="glyphicon glyphicon-remove"></span>\n </a>\n </div>\n <div class="header-text horizontal middle">\n <cloud-provider-logo provider="ctrl.serverGroup.type" height="\'36px\'" width="\'36px\'"></cloud-provider-logo>\n <h3 class="horizontal middle space-between flex-1" select-on-dbl-click>\n {{ctrl.serverGroup.name}}\n <render-if-feature feature="entityTags">\n <entity-notifications\n entity="ctrl.serverGroup"\n application="ctrl.application"\n placement="bottom"\n h-offset-percent="90%"\n entity-type="serverGroup"\n page-location="details"\n on-update="ctrl.application.serverGroups.refresh()"\n ></entity-notifications>\n </render-if-feature>\n </h3>\n </div>\n <div>\n <div class="actions" ng-class="{ insights: ctrl.serverGroup.insightActions.length > 0 }">\n <div class="dropdown" uib-dropdown dropdown-append-to-body>\n <button type="button" class="btn btn-sm btn-primary dropdown-toggle" uib-dropdown-toggle>\n Server Group Actions <span class="caret"></span>\n </button>\n <ul class="dropdown-menu" uib-dropdown-menu role="menu">\n <li><a href ng-if=" !ctrl.serverGroup.isDisabled" ng-click="ctrl.rollbackServerGroup()">Rollback</a></li>\n <li role="presentation" class="divider" ng-if=" !ctrl.serverGroup.isDisabled"></li>\n <li><a href ng-click="ctrl.resizeServerGroup()">Resize</a></li>\n <li><a href ng-if=" !ctrl.serverGroup.isDisabled" ng-click="ctrl.disableServerGroup()">Disable</a></li>\n <li>\n <a href ng-if="ctrl.serverGroup.isDisabled && !ctrl.isEnableLocked()" ng-click="ctrl.enableServerGroup()"\n >Enable</a\n >\n </li>\n <li class="disabled" ng-if="ctrl.isEnableLocked()">\n <a\n uib-tooltip="Cannot enable this server group until resize operation completes"\n tooltip-placement="left"\n >\n <span class="small glyphicon glyphicon-lock"></span>\n Enable\n </a>\n </li>\n <li><a href ng-click="ctrl.destroyServerGroup()">Destroy</a></li>\n <li><migrator application="ctrl.application" server-group="ctrl.serverGroup"></migrator></li>\n <render-if-feature feature="entityTags">\n <add-entity-tag-links\n component="ctrl.serverGroup"\n application="ctrl.application"\n entity-type="serverGroup"\n owner-options="ctrl.entityTagTargets"\n on-update="ctrl.application.serverGroups.refresh"\n ></add-entity-tag-links>\n </render-if-feature>\n </ul>\n </div>\n <div class="dropdown" ng-if="ctrl.serverGroup.insightActions.length > 0" uib-dropdown dropdown-append-to-body>\n <button type="button" class="btn btn-sm btn-default dropdown-toggle" uib-dropdown-toggle>\n Insight <span class="caret"></span>\n </button>\n <ul class="dropdown-menu" uib-dropdown-menu role="menu">\n <li ng-repeat="action in ctrl.serverGroup.insightActions">\n <a target="_blank" href="{{action.url}}">{{action.label}}</a>\n </li>\n </ul>\n </div>\n </div>\n </div>\n </div>\n <div class="band band-info" ng-if="ctrl.serverGroup.isDisabled">Disabled {{ctrl.disabledDate | timestamp}}</div>\n <div class="content" ng-if="!ctrl.state.loading">\n <server-group-running-tasks-details\n server-group="ctrl.serverGroup"\n application="ctrl.application"\n ></server-group-running-tasks-details>\n <collapsible-section heading="General" expanded="true">\n <dl class="dl-horizontal dl-narrow">\n <dt>Created</dt>\n <dd>{{ctrl.serverGroup.createdTime | timestamp}}</dd>\n <render-if-feature feature="entityTags">\n <entity-source metadata="ctrl.serverGroup.entityTags.creationMetadata"></entity-source>\n <view-changes-link\n change-config="ctrl.changeConfig"\n jar-diffs="ctrl.jarDiffs"\n link-text="view changes"\n name-item="ctrl.serverGroup"\n ></view-changes-link>\n </render-if-feature>\n <dt>In</dt>\n <dd>\n <account-tag account="ctrl.serverGroup.account" pad="right"></account-tag>\n <br />\n {{ctrl.serverGroup.region}}\n </dd>\n <dt>ECS Cluster</dt>\n <dd>{{ctrl.serverGroup.ecsCluster}}</dd>\n <dt>VPC ID</dt>\n <dd>{{ctrl.serverGroup.vpcId}}</dd>\n </dl>\n </collapsible-section>\n <collapsible-section heading="Definitions" expanded="true">\n <dl class="horizontal-when-filters-collapsed">\n <dt>Task Name</dt>\n <dd>{{ctrl.serverGroup.taskDefinition.taskName}}</dd>\n\n <dt>Container URL</dt>\n <dd>{{ctrl.serverGroup.taskDefinition.containerImage}}</dd>\n\n <dt>Container IAM Profile</dt>\n <dd>{{ctrl.serverGroup.taskDefinition.iamRole}}</dd>\n\n <dt ng-if="ctrl.serverGroup.taskDefinition.containerPort">Container Port</dt>\n <dd ng-if="ctrl.serverGroup.taskDefinition.containerPort">{{ctrl.serverGroup.taskDefinition.containerPort}}</dd>\n\n <dt>Container CPU Units</dt>\n <dd>{{ctrl.serverGroup.taskDefinition.cpuUnits}}</dd>\n\n <dt ng-if="ctrl.serverGroup.taskDefinition.memoryReservation">Container Reserved Memory</dt>\n <dd ng-if="ctrl.serverGroup.taskDefinition.memoryReservation">\n {{ctrl.serverGroup.taskDefinition.memoryReservation}} mb\n </dd>\n\n <dt ng-if="ctrl.serverGroup.taskDefinition.memoryLimit">Container Memory Limit</dt>\n <dd ng-if="ctrl.serverGroup.taskDefinition.memoryLimit">{{ctrl.serverGroup.taskDefinition.memoryLimit}} mb</dd>\n </dl>\n </collapsible-section>\n <collapsible-section heading="Environment Variables" expanded="false">\n <div ng-if="!ctrl.serverGroup.taskDefinition.environmentVariables.length">\n This server group has no environment variables\n </div>\n <dl ng-if="ctrl.serverGroup.taskDefinition.environmentVariables.length">\n <dt ng-repeat-start="variable in ctrl.serverGroup.taskDefinition.environmentVariables">{{variable.name}}</dt>\n <dd ng-repeat-end>{{variable.value}}</dd>\n </dl>\n </collapsible-section>\n <collapsible-section heading="Health" expanded="true" ng-if="ctrl.serverGroup.instanceCounts.total > 0">\n <dl class="dl-horizontal dl-narrow" ng-if="ctrl.serverGroup">\n <dt>Instances</dt>\n <dd>\n <health-counts container="ctrl.serverGroup.instanceCounts" class="pull-left"></health-counts>\n </dd>\n </dl>\n </collapsible-section>\n <collapsible-section heading="{{ctrl.firewallsLabel}}" expanded="false">\n <ul>\n <li ng-repeat="securityGroup in ctrl.serverGroup.securityGroups">{{securityGroup}}</li>\n </ul>\n </collapsible-section>\n <collapsible-section heading="Capacity" expanded="false">\n <dl class="dl-horizontal dl-narrow">\n <dt>Current</dt>\n <dd>{{ctrl.serverGroup.instances.length}}</dd>\n\n <dt>Desired</dt>\n <dd>{{ctrl.serverGroup.capacity.desired}}</dd>\n\n <dt>Min</dt>\n <dd>{{ctrl.serverGroup.capacity.min}}</dd>\n\n <dt>Max</dt>\n <dd>{{ctrl.serverGroup.capacity.max}}</dd>\n </dl>\n </collapsible-section>\n <collapsible-section heading="Scaling Policies" expanded="false">\n <dl class="horizontal-when-filters-collapsed">\n <dd\n ng-if="ctrl.serverGroup.metricAlarms.length > 0"\n ng-repeat="metricAlarmName in ctrl.serverGroup.metricAlarms"\n >\n {{metricAlarmName}}\n </dd>\n <dd ng-if="ctrl.serverGroup.metricAlarms.length <= 0"><i>There are no scaling policies assigned.</i></dd>\n </dl>\n </collapsible-section>\n <collapsible-section heading="Build data" ng-if="ctrl.serverGroup.buildInfo && ctrl.serverGroup.buildInfo.jenkins">\n <dl class="horizontal-when-filters-collapsed">\n <dt>Job</dt>\n <dd>{{ctrl.serverGroup.buildInfo.jenkins.name}}</dd>\n <dt>Package</dt>\n <dd>{{ctrl.serverGroup.buildInfo.package_name}}</dd>\n <dt>Build</dt>\n <dd>{{ctrl.serverGroup.buildInfo.jenkins.number}}</dd>\n <dt>Commit</dt>\n <dd>{{ctrl.truncateCommitHash()}}</dd>\n <dt>Version</dt>\n <dd>{{ctrl.serverGroup.buildInfo.version}}</dd>\n <dt>Build Link</dt>\n <dd><a target="_blank" href="{{ctrl.buildJenkinsLink()}}">{{ctrl.buildJenkinsLink()}}</a></dd>\n </dl>\n </collapsible-section>\n <collapsible-section heading="Server Group Logs">\n <ul>\n <li>\n <view-events-link server-group="ctrl.serverGroup"></view-events-link>\n </li>\n </ul>\n </collapsible-section>\n </div>\n</div>\n')}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/serverGroup/configure/wizard/serverGroupWizard.html",'<form name="form" class="form-horizontal" novalidate>\n <div ng-if="state.requiresTemplateSelection">\n <ng-include src="pages.templateSelection"></ng-include>\n </div>\n <div ng-if="!state.loaded" style="height: 200px">\n <h3 us-spinner="{radius:30, width:8, length: 16}"></h3>\n </div>\n <div ng-if="!state.requiresTemplateSelection">\n <v2-modal-wizard ng-show="state.loaded" heading="{{title}}" task-monitor="taskMonitor" dismiss="$dismiss()">\n <v2-wizard-page key="basicSettings" label="Basic Settings" mark-complete-on-view="false" done="true">\n <ng-include src="pages.basicSettings"></ng-include>\n </v2-wizard-page>\n <v2-wizard-page key="networking" label="Networking" done="true">\n <ng-include src="pages.networking"></ng-include>\n </v2-wizard-page>\n <v2-wizard-page key="taskDefinition" label="Task Definition" done="true">\n <ng-include src="pages.taskDefinition"></ng-include>\n </v2-wizard-page>\n <div ng-if="!command.useTaskDefinitionArtifact">\n <v2-wizard-page key="container" label="Container" done="true">\n <ng-include src="pages.container"></ng-include>\n </v2-wizard-page>\n </div>\n <v2-wizard-page key="horizontalScaling" label="Horizontal Scaling" done="true">\n <ng-include src="pages.horizontalScaling"></ng-include>\n </v2-wizard-page>\n <div ng-if="!command.useTaskDefinitionArtifact">\n <v2-wizard-page key="logging" label="Logging" done="true">\n <ng-include src="pages.logging"></ng-include>\n </v2-wizard-page>\n </div>\n <v2-wizard-page key="serviceDiscovery" label="Service Discovery" done="true">\n <ng-include ng-if="!command.useTaskDefinitionArtifact" src="pages.serviceDiscovery"></ng-include>\n <ng-include ng-if="command.useTaskDefinitionArtifact" src="pages.serviceDiscovery"></ng-include>\n </v2-wizard-page>\n <v2-wizard-page key="advanced" label="Advanced Settings" mark-complete-on-view="false" done="true">\n <ng-include src="pages.advancedSettings"></ng-include>\n </v2-wizard-page>\n </v2-modal-wizard>\n <div class="modal-footer" ng-if="state.loaded">\n <button ng-disabled="taskMonitor.submitting" class="btn btn-default btn-cancel" ng-click="ctrl.cancel()">\n Cancel\n </button>\n <submit-button\n data-test-id="ServerGroupWizard.submitButton"\n ng-if="ctrl.showSubmitButton()"\n is-disabled="!ctrl.isValid() || taskMonitor.submitting"\n label="command.viewState.submitButtonLabel"\n submitting="taskMonitor.submitting"\n on-click="ctrl.submit()"\n is-new="true"\n ></submit-button>\n </div>\n </div>\n</form>\n')}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/instance/details/instanceDetails.html",'<div class="text-center" ng-if="state.notFoundStandalone">\n <h3>Could not find instance {{instanceIdNotFound}}.</h3>\n <a ui-sref="home.infrastructure">Back to search results</a>\n</div>\n<div class="details-panel" ng-if="!state.notFoundStandalone">\n <div class="header">\n <instance-details-header\n health-state="instance.healthState"\n instance-id="instance ? instance.name : instanceIdNotFound"\n loading="state.loading"\n standalone="state.standalone"\n ></instance-details-header>\n <div ng-if="!state.loading">\n <div class="actions" ng-class="{ insights: instance.insightActions.length > 0 }">\n \x3c!-- TODO - find out what I should do with ng-if="instance.placement" --\x3e\n <div class="dropdown" uib-dropdown dropdown-append-to-body>\n <button\n type="button"\n class="btn btn-sm btn-primary dropdown-toggle"\n ng-disabled="disabled"\n uib-dropdown-toggle\n >\n Instance Actions <span class="caret"></span>\n </button>\n <ul class="dropdown-menu" uib-dropdown-menu role="menu">\n <li>\n <a href ng-click="ctrl.enableInstanceInDiscovery()" ng-if="ctrl.canRegisterWithDiscovery()"\n >Enable in Discovery</a\n >\n </li>\n <li>\n <a\n href\n ng-click="ctrl.disableInstanceInDiscovery()"\n ng-if="ctrl.hasHealthState(\'Discovery\', \'Up\') || ctrl.hasHealthState(\'Discovery\', \'Down\')"\n >Disable in Discovery</a\n >\n </li>\n <li>\n <a href ng-click="ctrl.registerInstanceWithLoadBalancer()" ng-if="ctrl.canRegisterWithLoadBalancer()"\n >Register with Load Balancer</a\n >\n </li>\n <li>\n <a href ng-click="ctrl.deregisterInstanceFromLoadBalancer()" ng-if="ctrl.canDeregisterFromLoadBalancer()"\n >Deregister from Load Balancer</a\n >\n </li>\n <li>\n <a href ng-click="ctrl.registerInstanceWithTargetGroup()" ng-if="ctrl.canRegisterWithTargetGroup()"\n >Register with Target Group</a\n >\n </li>\n <li>\n <a href ng-click="ctrl.deregisterInstanceFromTargetGroup()" ng-if="ctrl.canDeregisterFromTargetGroup()"\n >Deregister from Target Group</a\n >\n </li>\n \x3c!--<li role="presentation" class="divider" ng-if="instance.health.length > 0"></li>--\x3e\n </ul>\n </div>\n <div class="dropdown" ng-if="instance.insightActions.length > 0" uib-dropdown dropdown-append-to-body>\n <button type="button" class="btn btn-sm btn-default dropdown-toggle" uib-dropdown-toggle>\n Insight <span class="caret"></span>\n </button>\n <ul class="dropdown-menu" uib-dropdown-menu role="menu">\n <li ng-repeat="action in instance.insightActions">\n <a target="_blank" href="{{action.url}}">{{action.label}}</a>\n </li>\n </ul>\n </div>\n </div>\n </div>\n </div>\n <div class="content" data-test-id="instanceDetails.content" ng-if="!state.loading && instance">\n <collapsible-section heading="Instance Information" expanded="true">\n <dl class="dl-horizontal dl-narrow">\n <dt>Launched</dt>\n <dd ng-if="instance.launchTime">{{instance.launchTime | timestamp}}</dd>\n <dd ng-if="!instance.launchTime">(Unknown)</dd>\n <dt ng-if="instance.serverGroup">Server Group</dt>\n <dd ng-if="instance.serverGroup">\n <a\n ui-sref="^.serverGroup({region: instance.region,\n accountId: instance.account,\n serverGroup: instance.serverGroup,\n provider: instance.provider})"\n >{{instance.serverGroup}}</a\n >\n </dd>\n <dt ng-if="instance.imageId">Image ID</dt>\n <dd ng-if="instance.imageId">{{instance.imageId}}</dd>\n </dl>\n </collapsible-section>\n <collapsible-section heading="Status" expanded="true">\n <p ng-if="instance.healthState !== \'Starting\' && !healthMetrics.length">\n No health metrics found for this instance\n </p>\n <p ng-if="instance.healthState === \'Starting\' && !healthMetrics.length">\n <span class="glyphicon glyphicon-Starting-triangle"></span> <strong>Starting</strong>\n </p>\n\n <dl class="horizontal-when-filters-collapsed">\n <dt ng-repeat-start="metric in healthMetrics | orderBy: \'type\'">{{metric.type | robotToHuman}}</dt>\n <dd ng-repeat-end>\n <div ng-if="metric.type !== \'LoadBalancer\' && metric.type !== \'TargetGroup\'">\n <span\n uib-tooltip="{{metric.state.toLowerCase() === \'down\' ? metric.description : \'\'}}"\n tooltip-placement="left"\n >\n <span class="glyphicon glyphicon-{{metric.state}}-triangle"></span>\n {{metric.state | robotToHuman}}\n </span>\n <span class="pad-left small">\n <a ng-if="metric.healthCheckUrl" target="_blank" href="{{metric.healthCheckUrl}}">Health Check</a>\n <span ng-if="metric.healthCheckUrl && metric.statusPageUrl"> | </span>\n <a ng-if="metric.statusPageUrl" target="_blank" href="{{metric.statusPageUrl}}">Status</a>\n </span>\n </div>\n <div\n ng-if="metric.type === \'LoadBalancer\' && metric.loadBalancers.length"\n ng-repeat="loadBalancer in metric.loadBalancers"\n >\n <instance-load-balancer-health load-balancer="loadBalancer"></instance-load-balancer-health>\n </div>\n <div\n ng-if="metric.type === \'TargetGroup\' && metric.targetGroups.length"\n ng-repeat="targetGroup in metric.targetGroups"\n >\n <instance-load-balancer-health\n load-balancer="targetGroup"\n ip-address="baseIpAddress"\n ></instance-load-balancer-health>\n </div>\n </dd>\n </dl>\n </collapsible-section>\n <collapsible-section heading="Networking">\n <dl class="horizontal-when-filters-collapsed">\n <dt ng-if="instance.vpcId">VPC</dt>\n <dd ng-if="instance.vpcId"><vpc-tag vpc-id="instance.vpcId"></vpc-tag></dd>\n <dt ng-if="instance.subnetId">Subnet</dt>\n <dd ng-if="instance.subnetId"><subnet-tag subnet-id="instance.subnetId"></subnet-tag></dd>\n\n <dt ng-if="instance.privateAddress || instance.networkInterface">IP</dt>\n <dd ng-if="instance.networkInterface.privateIpv4Address">\n Private address (ENI):\n <a href="http://{{instance.networkInterface.privateIpv4Address}}" target="_blank"\n >{{instance.networkInterface.privateIpv4Address}}</a\n >\n <copy-to-clipboard\n class="copy-to-clipboard copy-to-clipboard-sm"\n text="instance.networkInterface.privateIpv4Address"\n tool-tip="\'Copy to clipboard\'"\n >\n </copy-to-clipboard>\n </dd>\n <dd ng-if="instance.networkInterface.ipv6Address">\n Private address (ENI):\n <a href="http://{{instance.networkInterface.ipv6Address}}" target="_blank"\n >{{instance.networkInterface.ipv6Address}}</a\n >\n <copy-to-clipboard\n class="copy-to-clipboard copy-to-clipboard-sm"\n text="instance.networkInterface.ipv6Address"\n tool-tip="\'Copy to clipboard\'"\n >\n </copy-to-clipboard>\n </dd>\n <dd ng-if="instance.privateAddress">\n Private address (Bridge):\n <a href="http://{{instance.privateAddress}}" target="_blank">{{instance.privateAddress}}</a>\n <copy-to-clipboard\n class="copy-to-clipboard copy-to-clipboard-sm"\n text="instance.privateAddress"\n tool-tip="\'Copy to clipboard\'"\n >\n </copy-to-clipboard>\n </dd>\n </dl>\n </collapsible-section>\n <collapsible-section heading="Console Output" ng-if="baseIpAddress">\n <ul>\n <li>\n <console-output-link instance="instance"></console-output-link>\n </li>\n </ul>\n </collapsible-section>\n <instance-links\n address="baseIpAddress"\n application="application"\n instance="instance"\n moniker="moniker"\n environment="environment"\n ></instance-links>\n </div>\n <div class="content" ng-if="!state.loading && !instance">\n <div class="content-section">\n <div class="content-body text-center">\n <h3>Instance not found.</h3>\n </div>\n </div>\n </div>\n</div>\n')}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("ecs/src/securityGroup/details/securityGroupDetail.html",'<div class="text-center" ng-if="state.notFound">\n <h3>Could not find <firewall-label label="firewall"></firewall-label> {{group}}.</h3>\n <a ui-sref="home.infrastructure">Back to search results</a>\n</div>\n<div class="details-panel" ng-if="!state.notFound">\n <div class="header">\n <div class="close-button" ng-if="!state.standalone">\n <a class="btn btn-link" ui-sref="^">\n <span class="glyphicon glyphicon-remove"></span>\n </a>\n </div>\n <div ng-if="state.loading" class="horizontal center middle">\n <loading-spinner size="\'small\'"></loading-spinner>\n </div>\n <div class="header-text horizontal middle" ng-if="!state.loading">\n <span class="glyphicon glyphicon-transfer"></span>\n <h3 class="horizontal middle space-between flex-1" select-on-dbl-click>\n {{securityGroup.name || \'(not found)\'}}\n <render-if-feature feature="entityTags">\n <entity-notifications\n entity="securityGroup"\n application="ctrl.application"\n placement="bottom"\n h-offset-percent="90%"\n entity-type="securityGroup"\n page-location="details"\n on-update="ctrl.application.securityGroups.refresh()"\n ></entity-notifications>\n </render-if-feature>\n </h3>\n </div>\n </div>\n <div class="content" ng-if="!state.loading">\n <collapsible-section heading="{{ctrl.firewallLabel}} Details" expanded="true">\n <dl class="dl-horizontal dl-medium">\n <dt>ID</dt>\n <dd>{{securityGroup.id}}</dd>\n <dt>Account</dt>\n <dd>\n <account-tag account="securityGroup.accountName"></account-tag>\n </dd>\n <dt>Region</dt>\n <dd>{{securityGroup.region}}</dd>\n <dt>VPC</dt>\n <dd>\n <vpc-tag vpc-id="securityGroup.vpcId"></vpc-tag>\n </dd>\n <dt>Description</dt>\n <dd>{{securityGroup.description}}</dd>\n </dl>\n </collapsible-section>\n <collapsible-section heading="IP Range Rules ({{ipRules.length}})" expanded="{{ipRules.length > 0}}">\n <div ng-if="!ipRules.length">None</div>\n\n <dl\n ng-class="insightCtrl.vm.filtersExpanded ? \'\' : \'dl-horizontal dl-medium\'"\n ng-repeat="ipRangeRule in ipRules | orderBy: \'range.address\'"\n >\n <dt>IP Range</dt>\n <dd>{{ipRangeRule.address}}</dd>\n <dt>Port Ranges</dt>\n <dd ng-repeat="rule in ipRangeRule.rules">\n <span ng-if="rule.protocol === \'-1\'">\n All ports and protocols\n <div ng-if="ipRangeRule.rules.length > 1">\n <em>Additional port ranges are specified, but redundant:</em>\n </div>\n </span>\n <span ng-if="rule.protocol !== \'-1\'"> {{rule.protocol}}: {{rule.startPort}} → {{rule.endPort}} </span>\n </dd>\n </dl>\n </collapsible-section>\n <collapsible-section\n heading="{{ctrl.firewallLabel}} Rules ({{securityGroupRules.length || 0}})"\n expanded="{{securityGroupRules.length > 0}}"\n >\n <div ng-if="!securityGroupRules.length">None</div>\n\n <dl\n ng-class="insightCtrl.vm.filtersExpanded ? \'\' : \'dl-horizontal dl-medium\'"\n ng-repeat="rule in securityGroupRules | orderBy: \'securityGroup.name\' "\n >\n <dt>\n <firewall-label label="Firewall"></firewall-label>\n </dt>\n <dd ng-if="rule.securityGroup.name">\n <a\n ui-sref="^.firewallDetails({name: rule.securityGroup.name, accountId: rule.securityGroup.accountName, region: rule.securityGroup.region, vpcId: rule.securityGroup.vpcId, provider: \'ecs\'})"\n >\n <account-tag\n account="rule.securityGroup.accountName || rule.securityGroup.accountId"\n ng-if="rule.securityGroup.accountName !== securityGroup.accountName"\n ></account-tag>\n {{rule.securityGroup.name}} ({{rule.securityGroup.id}})\n </a>\n </dd>\n <dt>Port Ranges</dt>\n <dd ng-repeat="portRange in rule.rules">\n {{portRange.protocol}}: {{portRange.startPort}} → {{portRange.endPort}}\n </dd>\n </dl>\n </collapsible-section>\n </div>\n</div>\n')}]);export{At as ECS_MODULE};
|
|
2
2
|
//# sourceMappingURL=index.js.map
|