11/*
2- * Copyright 2012 Netflix, Inc.
2+ * Copyright 2014 Netflix, Inc.
33 *
44 * Licensed under the Apache License, Version 2.0 (the "License");
55 * you may not use this file except in compliance with the License.
1515 */
1616package com.netflix.asgard
1717
18- import com.amazonaws.AmazonServiceException
19- import com.amazonaws.services.simpledb.model.Attribute
20- import com.amazonaws.services.simpledb.model.Item
21- import com.amazonaws.services.simpledb.model.ReplaceableAttribute
22- import com.netflix.asgard.cache.CacheInitializer
2318import com.netflix.asgard.collections.GroupedAppRegistrationSet
2419import com.netflix.asgard.model.MonitorBucketType
25- import org.joda.time.DateTime
26- import org.springframework.beans.factory.InitializingBean
27-
28- class ApplicationService implements CacheInitializer , InitializingBean {
29-
30- static transactional = false
31-
32- /* * The name of SimpleDB domain that stores the cloud application registry. */
33- String domainName
34-
35- def grailsApplication // injected after construction
36- def awsAutoScalingService
37- def awsClientService
38- def awsEc2Service
39- def awsLoadBalancerService
40- def awsSimpleDbService
41- Caches caches
42- def configService
43- def fastPropertyService
44- def mergedInstanceGroupingService
45- def taskService
46-
47- void afterPropertiesSet () {
48- domainName = configService. applicationsDomain
49- }
5020
51- void initializeCaches () {
52- caches. allApplications. ensureSetUp({ retrieveApplications() })
53- }
21+ interface ApplicationService {
22+ List<AppRegistration > getRegisteredApplications (UserContext userContext )
5423
55- private Collection<AppRegistration > retrieveApplications () {
56- List<Item > items = awsSimpleDbService. selectAll(domainName). sort { it. name. toLowerCase() }
57- items. collect { AppRegistration . from(it) }
58- }
59-
60- List<AppRegistration > getRegisteredApplications (UserContext userContext ) {
61- caches. allApplications. list(). sort { it. name }
62- }
63-
64- List<AppRegistration > getRegisteredApplicationsForLoadBalancer (UserContext userContext ) {
65- new ArrayList<AppRegistration > (getRegisteredApplications(userContext). findAll {
66- Relationships . checkAppNameForLoadBalancer(it. name)
67- })
68- }
69-
70- GroupedAppRegistrationSet getGroupedRegisteredApplications (UserContext ctx ) {
71- new GroupedAppRegistrationSet (getRegisteredApplications(ctx))
72- }
24+ List<AppRegistration > getRegisteredApplicationsForLoadBalancer (UserContext userContext )
7325
74- AppRegistration getRegisteredApplication (UserContext userContext , String nameInput , From from = From . AWS ) {
75- if (! nameInput) { return null }
76- String name = nameInput. toLowerCase()
77- if (from == From . CACHE ) {
78- return caches. allApplications. get(name)
79- }
80- Item item = awsSimpleDbService. selectOne(domainName, name. toUpperCase())
81- AppRegistration appRegistration = AppRegistration . from(item)
82- caches. allApplications. put(name, appRegistration)
83- appRegistration
84- }
26+ GroupedAppRegistrationSet getGroupedRegisteredApplications (UserContext ctx )
8527
86- AppRegistration getRegisteredApplicationForLoadBalancer (UserContext userContext , String name ) {
87- Relationships . checkAppNameForLoadBalancer(name) ? getRegisteredApplication(userContext, name) : null
88- }
28+ AppRegistration getRegisteredApplication (UserContext userContext , String nameInput )
8929
90- CreateApplicationResult createRegisteredApplication (UserContext userContext , String nameInput , String group ,
91- String type , String description , String owner , String email , MonitorBucketType monitorBucketType ,
92- String tags ) {
93- String name = nameInput. toLowerCase()
94- CreateApplicationResult result = new CreateApplicationResult ()
95- result. appName = name
96- if (getRegisteredApplication(userContext, name)) {
97- result. appCreateException = new IllegalStateException (" Can't add Application ${ name} . It already exists." )
98- return result
99- }
100- String nowEpoch = new DateTime (). millis as String
101- Collection<ReplaceableAttribute > attributes = buildAttributesList(group, type, description, owner, email,
102- monitorBucketType, tags, false )
103- attributes << new ReplaceableAttribute (' createTs' , nowEpoch, false )
104- String creationLogMessage = " Create registered app ${ name} , type ${ type} , owner ${ owner} , email ${ email} "
105- taskService. runTask(userContext, creationLogMessage, { task ->
106- try {
107- awsSimpleDbService. save(domainName, name. toUpperCase(), attributes)
108- result. appCreated = true
109- } catch (AmazonServiceException e) {
110- result. appCreateException = e
111- }
112- }, Link . to(EntityType . application, name))
113- getRegisteredApplication(userContext, name)
114- result
115- }
30+ AppRegistration getRegisteredApplication (UserContext userContext , String nameInput , From from )
11631
117- private static Collection<ReplaceableAttribute > buildAttributesList (String group , String type , String description ,
118- String owner , String email , MonitorBucketType monitorBucketType , String tags ,
119- Boolean replaceExistingValues ) {
120-
121- Check . notNull(monitorBucketType, MonitorBucketType , ' monitorBucketType' )
122- String nowEpoch = new DateTime (). millis as String
123- Collection<ReplaceableAttribute > attributes = []
124- attributes << new ReplaceableAttribute (' group' , group ?: ' ' , replaceExistingValues)
125- attributes << new ReplaceableAttribute (' type' , Check . notEmpty(type), replaceExistingValues)
126- attributes << new ReplaceableAttribute (' description' , Check . notEmpty(description), replaceExistingValues)
127- attributes << new ReplaceableAttribute (' owner' , Check . notEmpty(owner), replaceExistingValues)
128- attributes << new ReplaceableAttribute (' email' , Check . notEmpty(email), replaceExistingValues)
129- attributes << new ReplaceableAttribute (' monitorBucketType' , monitorBucketType. name(), replaceExistingValues)
130- attributes << new ReplaceableAttribute (' updateTs' , nowEpoch, replaceExistingValues)
131- if (tags) {
132- attributes << new ReplaceableAttribute (' tags' , tags, replaceExistingValues)
133- }
134- return attributes
135- }
32+ AppRegistration getRegisteredApplicationForLoadBalancer (UserContext userContext , String name )
13633
137- void updateRegisteredApplication (UserContext userContext , String name , String group , String type , String desc ,
138- String owner , String email , String tags , MonitorBucketType bucketType ) {
139- Collection<ReplaceableAttribute > attributes = buildAttributesList(group, type, desc, owner, email,
140- bucketType, tags, true )
141- taskService. runTask(userContext,
142- " Update registered app ${ name} , type ${ type} , owner ${ owner} , email ${ email} " , { task ->
143- awsSimpleDbService. save(domainName, name. toUpperCase(), attributes)
144- if (! tags) {
145- awsSimpleDbService. delete(domainName, name. toUpperCase(), [new Attribute (). withName(' tags' )])
146- }
147- }, Link . to(EntityType . application, name))
148- getRegisteredApplication(userContext, name)
149- }
34+ ApplicationModificationResult createRegisteredApplication (UserContext userContext , String name , String group ,
35+ String type , String description , String owner ,
36+ String email , MonitorBucketType monitorBucketType ,
37+ String tags )
15038
151- void deleteRegisteredApplication (UserContext userContext , String name ) {
152- Check . notEmpty(name, " name" )
153- validateDelete(userContext, name)
154- taskService. runTask(userContext, " Delete registered app ${ name} " , { task ->
155- awsSimpleDbService. delete(domainName, name. toUpperCase())
156- }, Link . to(EntityType . application, name))
157- getRegisteredApplication(userContext, name)
158- }
39+ ApplicationModificationResult updateRegisteredApplication (UserContext userContext , String name , String group ,
40+ String type , String desc , String owner ,
41+ String email , MonitorBucketType bucketType ,
42+ String tags )
15943
160- private void validateDelete (UserContext userContext , String name ) {
161- List<String > objectsWithEntities = []
162- if (awsAutoScalingService. getAutoScalingGroupsForApp(userContext, name)) {
163- objectsWithEntities. add(' Auto Scaling Groups' )
164- }
165- if (awsLoadBalancerService. getLoadBalancersForApp(userContext, name)) {
166- objectsWithEntities. add(' Load Balancers' )
167- }
168- if (awsEc2Service. getSecurityGroupsForApp(userContext, name)) {
169- objectsWithEntities. add(' Security Groups' )
170- }
171- if (mergedInstanceGroupingService. getMergedInstances(userContext, name)) {
172- objectsWithEntities. add(' Instances' )
173- }
174- if (fastPropertyService. getFastPropertiesByAppName(userContext, name)) {
175- objectsWithEntities. add(' Fast Properties' )
176- }
177-
178- if (objectsWithEntities) {
179- String referencesString = objectsWithEntities. join(' , ' )
180- String message = " ${ name} ineligible for delete because it still references ${ referencesString} "
181- throw new ValidationException (message)
182- }
183- }
44+ void deleteRegisteredApplication (UserContext userContext , String name )
18445
18546 /**
18647 * Get the email address of the relevant app, or empty string if no email address can be found for the specified
@@ -189,9 +50,7 @@ class ApplicationService implements CacheInitializer, InitializingBean {
18950 * @param appName the name of the app that has the email address
19051 * @return the email address associated with the app, or empty string if no email address can be found
19152 */
192- String getEmailFromApp (UserContext userContext , String appName ) {
193- getRegisteredApplication(userContext, appName)?. email ?: ' '
194- }
53+ String getEmailFromApp (UserContext userContext , String appName )
19554
19655 /**
19756 * Provides a string to use for monitoring bucket, either provided an empty string, cluster name or app name based
@@ -202,33 +61,22 @@ class ApplicationService implements CacheInitializer, InitializingBean {
20261 * @param clusterName value to return if the application's monitor bucket type is 'cluster'
20362 * @return appName or clusterName or empty string, based on the application's monitorBucketType
20463 */
205- String getMonitorBucket (UserContext userContext , String appName , String clusterName ) {
206- MonitorBucketType type = getRegisteredApplication(userContext, appName)?. monitorBucketType
207- type == MonitorBucketType . application ? appName : type == MonitorBucketType . cluster ? clusterName : ' '
208- }
64+ String getMonitorBucket (UserContext userContext , String appName , String clusterName )
20965}
21066
21167/**
212- * Records the results of trying to create an Application.
68+ * Records the results of trying to modify an Application.
21369 */
214- class CreateApplicationResult {
215- String appName
216- Boolean appCreated
217- Exception appCreateException
70+ class ApplicationModificationResult {
71+ boolean successful
72+ String message
21873
21974 String toString () {
220- StringBuilder output = new StringBuilder ()
221- if (appCreated) {
222- output. append(" Application '${ appName} ' has been created. " )
223- }
224- if (appCreateException) {
225- output. append(" Could not create Application '${ appName} ': ${ appCreateException} . " )
226- }
227- output. toString()
75+ return message
22876 }
22977
23078 Boolean succeeded () {
231- appCreated && ! appCreateException
79+ return successful
23280 }
23381}
23482
0 commit comments