From d19531232c24beeb35b9898704633cf81b7160c0 Mon Sep 17 00:00:00 2001 From: NaiJi Date: Mon, 17 Oct 2022 17:42:23 +0000 Subject: [PATCH] feat(digital-ocean): Implement endpoints for server creation and deletion --- .../digital_ocean/digital_ocean.dart | 136 +++++++----------- .../server_providers/hetzner/hetzner.dart | 1 - .../server_installation_cubit.dart | 2 +- lib/logic/models/server_basic_info.dart | 4 - 4 files changed, 51 insertions(+), 92 deletions(-) diff --git a/lib/logic/api_maps/rest_maps/server_providers/digital_ocean/digital_ocean.dart b/lib/logic/api_maps/rest_maps/server_providers/digital_ocean/digital_ocean.dart index dafda8c4..125fe3bd 100644 --- a/lib/logic/api_maps/rest_maps/server_providers/digital_ocean/digital_ocean.dart +++ b/lib/logic/api_maps/rest_maps/server_providers/digital_ocean/digital_ocean.dart @@ -95,6 +95,9 @@ class DigitalOceanApi extends ServerProviderApi with VolumeProviderApi { final Response dbCreateResponse; final Dio client = await getClient(); try { + final List volumes = await getVolumes(); + await Future.delayed(const Duration(seconds: 6)); + dbCreateResponse = await client.post( '/volumes', data: { @@ -109,11 +112,12 @@ class DigitalOceanApi extends ServerProviderApi with VolumeProviderApi { final dbSize = dbCreateResponse.data['volume']['size_gigabytes']; final dbName = dbCreateResponse.data['volume']['name']; volume = ServerVolume( - id: dbId, + id: volumes.length, name: dbName, sizeByte: dbSize, serverId: null, linuxDevice: null, + uuid: dbId, ); } catch (e) { print(e); @@ -296,36 +300,9 @@ class DigitalOceanApi extends ServerProviderApi with VolumeProviderApi { required final String domainName, required final String serverType, }) async { - ServerHostingDetails? details; - - final ServerVolume? newVolume = await createVolume(); - if (newVolume == null) { - return details; - } - - details = await createServerWithVolume( - dnsApiToken: dnsApiToken, - rootUser: rootUser, - domainName: domainName, - dataBase: newVolume, - serverType: serverType, - ); - - return details; - } - - Future createServerWithVolume({ - required final String dnsApiToken, - required final User rootUser, - required final String domainName, - required final ServerVolume dataBase, - required final String serverType, - }) async { - final Dio client = await getClient(); + ServerHostingDetails? serverDetails; final String dbPassword = StringGenerators.dbPassword(); - final int dbId = dataBase.id; - final String? dbUuid = dataBase.uuid; final String apiToken = StringGenerators.apiToken(); final String hostname = getHostnameFromDomain(domainName); @@ -334,58 +311,44 @@ class DigitalOceanApi extends ServerProviderApi with VolumeProviderApi { base64.encode(utf8.encode(rootUser.password ?? 'PASS')); final String userdataString = - "#cloud-config\nruncmd:\n- curl https://git.selfprivacy.org/SelfPrivacy/selfprivacy-nixos-infect/raw/branch/master/nixos-infect | PROVIDER=hetzner NIX_CHANNEL=nixos-21.05 DOMAIN='$domainName' LUSER='${rootUser.login}' ENCODED_PASSWORD='$base64Password' CF_TOKEN=$dnsApiToken DB_PASSWORD=$dbPassword API_TOKEN=$apiToken HOSTNAME=$hostname bash 2>&1 | tee /tmp/infect.log"; + "#cloud-config\nruncmd:\n- curl https://git.selfprivacy.org/SelfPrivacy/selfprivacy-nixos-infect/raw/branch/master/nixos-infect | PROVIDER=digital-ocean NIX_CHANNEL=nixos-21.05 DOMAIN='$domainName' LUSER='${rootUser.login}' ENCODED_PASSWORD='$base64Password' CF_TOKEN=$dnsApiToken DB_PASSWORD=$dbPassword API_TOKEN=$apiToken HOSTNAME=$hostname bash 2>&1 | tee /tmp/infect.log"; print(userdataString); - final Map data = { - 'name': hostname, - 'server_type': serverType, - 'start_after_create': false, - 'image': 'ubuntu-20.04', - 'volumes': dbUuid == null ? [dbId] : [dbUuid], - 'networks': [], - 'user_data': userdataString, - 'labels': {}, - 'automount': true, - 'location': 'fsn1' - }; - print('Decoded data: $data'); - - ServerHostingDetails? serverDetails; - DioError? hetznerError; - bool success = false; - + final Dio client = await getClient(); try { + final Map data = { + 'name': hostname, + 'size': serverType, + 'image': 'ubuntu-20-04-x64', + 'user_data': userdataString, + 'region': region!, + }; + print('Decoded data: $data'); + final Response serverCreateResponse = await client.post( - '/servers', + '/droplets', data: data, ); - print(serverCreateResponse.data); - serverDetails = ServerHostingDetails( - id: serverCreateResponse.data['server']['id'], - ip4: serverCreateResponse.data['server']['public_net']['ipv4']['ip'], - createTime: DateTime.now(), - volume: dataBase, - apiToken: apiToken, - provider: ServerProvider.hetzner, - ); - success = true; - } on DioError catch (e) { - print(e); - hetznerError = e; + + final int serverId = serverCreateResponse.data['server']['id']; + final ServerVolume? newVolume = await createVolume(); + final bool attachedVolume = + await attachVolume(newVolume!.uuid!, serverId); + + if (attachedVolume) { + serverDetails = ServerHostingDetails( + id: serverId, + ip4: serverCreateResponse.data['droplet']['networks']['v4'][0], + createTime: DateTime.now(), + volume: newVolume, + apiToken: apiToken, + provider: ServerProvider.digitalOcean, + ); + } } catch (e) { print(e); } finally { - client.close(); - } - - if (!success) { - await Future.delayed(const Duration(seconds: 10)); - await deleteVolume(dbUuid ?? dbId.toString()); - } - - if (hetznerError != null) { - throw hetznerError; + close(client); } return serverDetails; @@ -416,24 +379,26 @@ class DigitalOceanApi extends ServerProviderApi with VolumeProviderApi { final String hostname = getHostnameFromDomain(domainName); - final Response serversReponse = await client.get('/servers'); - final List servers = serversReponse.data['servers']; - final Map server = servers.firstWhere((final el) => el['name'] == hostname); - final List volumes = server['volumes']; + final ServerBasicInfo serverToRemove = (await getServers()).firstWhere( + (final el) => el.name == hostname, + ); + final ServerVolume volumeToRemove = (await getVolumes()).firstWhere( + (final el) => el.serverId == serverToRemove.id, + ); final List laterFutures = []; - for (final volumeId in volumes) { - await client.post('/volumes/$volumeId/actions/detach'); - } + await detachVolume(volumeToRemove.uuid!); await Future.delayed(const Duration(seconds: 10)); - for (final volumeId in volumes) { - laterFutures.add(client.delete('/volumes/$volumeId')); + try { + laterFutures.add(deleteVolume(volumeToRemove.uuid!)); + laterFutures.add(client.delete('/droplets/$serverToRemove.id')); + await Future.wait(laterFutures); + } catch (e) { + print(e); + } finally { + close(client); } - laterFutures.add(client.delete('/servers/${server['id']}')); - - await Future.wait(laterFutures); - close(client); } @override @@ -530,7 +495,6 @@ class DigitalOceanApi extends ServerProviderApi with VolumeProviderApi { ip: server.publicNet.ipv4.ip, reverseDns: server.publicNet.ipv4.reverseDns, created: server.created, - volumeId: server.volumes.isNotEmpty ? server.volumes[0] : 0, ), ) .toList(); diff --git a/lib/logic/api_maps/rest_maps/server_providers/hetzner/hetzner.dart b/lib/logic/api_maps/rest_maps/server_providers/hetzner/hetzner.dart index 5980f9cb..ba94dc53 100644 --- a/lib/logic/api_maps/rest_maps/server_providers/hetzner/hetzner.dart +++ b/lib/logic/api_maps/rest_maps/server_providers/hetzner/hetzner.dart @@ -532,7 +532,6 @@ class HetznerApi extends ServerProviderApi with VolumeProviderApi { ip: server.publicNet.ipv4.ip, reverseDns: server.publicNet.ipv4.reverseDns, created: server.created, - volumeId: server.volumes.isNotEmpty ? server.volumes[0] : 0, ), ) .toList(); diff --git a/lib/logic/cubit/server_installation/server_installation_cubit.dart b/lib/logic/cubit/server_installation/server_installation_cubit.dart index 360ec2e5..499ff49a 100644 --- a/lib/logic/cubit/server_installation/server_installation_cubit.dart +++ b/lib/logic/cubit/server_installation/server_installation_cubit.dart @@ -588,7 +588,7 @@ class ServerInstallationCubit extends Cubit { id: server.id, createTime: server.created, volume: ServerVolume( - id: server.volumeId, + id: 0, name: 'recovered_volume', sizeByte: 0, serverId: server.id, diff --git a/lib/logic/models/server_basic_info.dart b/lib/logic/models/server_basic_info.dart index 8670dc8c..b20803b0 100644 --- a/lib/logic/models/server_basic_info.dart +++ b/lib/logic/models/server_basic_info.dart @@ -5,14 +5,12 @@ class ServerBasicInfo { required this.reverseDns, required this.ip, required this.created, - required this.volumeId, }); final int id; final String name; final String reverseDns; final String ip; final DateTime created; - final int volumeId; } class ServerBasicInfoWithValidators extends ServerBasicInfo { @@ -26,7 +24,6 @@ class ServerBasicInfoWithValidators extends ServerBasicInfo { reverseDns: serverBasicInfo.reverseDns, ip: serverBasicInfo.ip, created: serverBasicInfo.created, - volumeId: serverBasicInfo.volumeId, isIpValid: isIpValid, isReverseDnsValid: isReverseDnsValid, ); @@ -37,7 +34,6 @@ class ServerBasicInfoWithValidators extends ServerBasicInfo { required final super.reverseDns, required final super.ip, required final super.created, - required final super.volumeId, required this.isIpValid, required this.isReverseDnsValid, });