@@ -36,6 +36,7 @@ const STATUS_CODES: { [k: string]: string; } = {
3636} ;
3737
3838const ERR_CODES : { [ k : string ] : string ; } = {
39+ 'VM_AE' : 'VM already exists.' ,
3940 'VM_DNE' : 'VM does not exist' ,
4041 'CLOUD_ERR' : 'Error from cloud provider'
4142} ;
@@ -67,14 +68,23 @@ class Provisioner {
6768 return this . doOAuth_ ( ) . then ( ( oauthObj : any ) => {
6869 this . state_ . oauth = oauthObj ;
6970 return this . getSshKey_ ( name ) ;
70- // Get SSH keys
7171 } ) . then ( ( keys : KeyPair ) => {
72+ // Get SSH keys
7273 this . state_ . ssh = keys ;
73- return this . setupDigitalOcean_ ( name , region , image , size ) ;
74- // Setup Digital Ocean (SSH key + droplet)
74+ return this . getDroplet_ ( name ) . then ( ( unused :any ) => {
75+ // Droplet exists so raise error
76+ return Promise . reject ( {
77+ 'errcode' : 'VM_AE' ,
78+ 'message' : 'Droplet ' + name + ' already exists'
79+ } ) ;
80+ } , ( e : Error ) => {
81+ // Droplet does not exist so continue creating new server
82+ // Setup Digital Ocean (SSH key + droplet)
83+ return this . setupDigitalOcean_ ( name , region , image , size ) ;
84+ } ) ;
7585 } ) . then ( ( ) => {
76- return this . doRequest_ ( 'GET' , 'droplets/' + this . state_ . cloud . vm . id ) ;
7786 // Get the droplet's configuration
87+ return this . doRequest_ ( 'GET' , 'droplets/' + this . state_ . cloud . vm . id ) ;
7888 } ) . then ( ( resp : any ) => {
7989 this . sendStatus_ ( 'CLOUD_DONE_VM' ) ;
8090 this . state_ . cloud . vm = resp . droplet ;
@@ -114,10 +124,36 @@ class Provisioner {
114124
115125 /**
116126 * Destroys cloud server; assumes OAuth has already been completed
127+ * This method will use this.waitDigitalOceanActions_() to wait until the server is deleted
117128 * @param {String } droplet name, as a string
118129 * @return {Promise.<void> }
119130 */
120131 private destroyServer_ = ( name : string ) : Promise < void > => {
132+ return this . doRequest_ ( 'GET' , 'droplets' ) . then ( ( resp : any ) => {
133+ // Find and delete the server with the same name
134+ return this . getDroplet_ ( name ) ;
135+ } ) . then ( ( resp :any ) => {
136+ this . state_ . cloud = { } ;
137+ this . state_ . cloud . vm = resp . droplet ;
138+ return this . doRequest_ ( 'DELETE' , 'droplets/' + resp . droplet . id ) ;
139+ } ) . then ( ( resp : any ) => {
140+ if ( resp . status . startsWith ( '204' ) ) {
141+ // Wait until server is deleted
142+ this . sendStatus_ ( 'CLOUD_WAITING_VM' ) ;
143+ return this . waitDigitalOceanActions_ ( ) ;
144+ } else {
145+ return Promise . reject ( new Error ( 'error deleting droplet' ) ) ;
146+ }
147+ } ) ;
148+ }
149+
150+ /**
151+ * Finds a droplet with this name
152+ * @param {String } droplet name, as a string
153+ * @return {Promise.<Object> }, resolves with {droplet: droplet_with_name}
154+ * or rejects if droplet doesn't exist
155+ */
156+ private getDroplet_ = ( name : string ) : Promise < Object > => {
121157 return this . doRequest_ ( 'GET' , 'droplets' ) . then ( ( resp : any ) => {
122158 // Find and delete the server with the same name
123159 for ( var i = 0 ; i < resp . droplets . length ; i ++ ) {
@@ -131,13 +167,6 @@ class Provisioner {
131167 'errcode' : 'VM_DNE' ,
132168 'message' : 'Droplet ' + name + ' doesnt exist'
133169 } ) ;
134- } ) . then ( ( resp : any ) => {
135- return this . doRequest_ ( 'DELETE' , 'droplets/' + resp . droplet . id ) ;
136- } ) . then ( ( resp : any ) => {
137- if ( resp . status . startsWith ( '204' ) ) {
138- return Promise . resolve < void > ( ) ;
139- }
140- return Promise . reject ( new Error ( 'error deleting droplet' ) ) ;
141170 } ) ;
142171 }
143172
0 commit comments