feat(hosting): Implement Digital Ocean hosting support #140
No reviewers
Labels
No Label
Blocked
Bug
Contributions welcome
Did not do
Errata
Feature request
Fixed
How To
Invalid
Needs design
No resolution
Priority
Critical
Priority
High
Priority
Low
Priority
Medium
Providers
Digital Ocean
Providers
Hetzner
Refactor
Severity
High
Severity
Low
Severity
Medium
Source
Community
Source
Core Team
Source
Stakeholders
Translations
Under investigation
No Milestone
No project
2 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: SelfPrivacy/selfprivacy.org.app#140
Loading…
Reference in New Issue
There is no content yet.
Delete Branch "digital-ocean"
Deleting a branch is permanent. Although the deleted branch may exist for a short time before cleaning up, in most cases it CANNOT be undone. Continue?
Added:
cc @inex
What is needed to be done now to get rid of WIP status:
WIP: feat: Implement Digital Ocean hosting supportto WIP: feat(hosting): Implement Digital Ocean hosting support7627b916fa
to657e4555d3
657e4555d3
to8f3b2dd20a
8f3b2dd20a
tobea2427590
bea2427590
tocdc47ecdb3
c8298c7600
toa7cbde663e
4a07f36d14
to6b90f83d0e
6b90f83d0e
toa7d74f1efc
a7d74f1efc
to661b5ca26f
661b5ca26f
to92b417a103
WIP: feat(hosting): Implement Digital Ocean hosting supportto feat(hosting): Implement Digital Ocean hosting support@inex All requested business cases for Digital Ocean are implemented. Now we need to test everything and I heavily encourage you to join me on this quest, because the end result is CRUCIAL, I am afraid all alone I can't guarantee it'll be as good as expected, I may miss a lot of stuff due to amount of our functionality.
3b2c04466e
to0c4da8eb9f
@ -270,3 +272,3 @@
"place_where_data": "Здесь будут жить ваши данные и SelfPrivacy-сервисы:",
"how": "Как получить API Token",
"hetzner_bad_key_error": "Hetzner API ключ неверен",
"provider_bad_key_error": "Provider API key is invalid",
Forgot the translation here, but in fact, we may just fill the en.json file and fill all other translations via weblate
@ -6,2 +19,4 @@
final httpLink = HttpLink(
'https://api.$rootAddress/graphql',
httpClient: IOClient(httpClient),
StagingOptions.stagingAcme ? IOClient(httpClient) : null
The default client looks slightly different, maybe we shouldn't override it?
@ -0,0 +95,4 @@
try {
final GraphQLClient client = await getClient();
response = await client.query$SystemServerProvider();
Use final and declare the type. Implication for some reason ignores our GraphQL model and we cannot use properly parsedData without type declaration.
@ -0,0 +96,4 @@
try {
final GraphQLClient client = await getClient();
response = await client.query$SystemServerProvider();
if (response.hasException) {
let's do
if (response.hasException || response.parsedData == null) {
just in caseCondition
response.hasException
checks for a graphql exception content toprint(response.exception.toString())
it.If
hasException
returns false, thenresponse.exception.toString()
won't do anything, it has nothing to do withparsedData
.@ -0,0 +99,4 @@
if (response.hasException) {
print(response.exception.toString());
}
final rawProviderValue = response.data!['system']['provider']['provider'];
Try not to access raw values. Using the constructor over parsedData will give us more type safety.
Example contructor code will be provided at the server_details.dart section.
@ -0,0 +56,4 @@
String get infectProviderName => 'digitalocean';
@override
String get appearanceProviderName => 'Digital Ocean';
More like
displayName
@ -0,0 +95,4 @@
@override
Future<Price?> getPricePerGb() async => Price(
value: 0.10,
currency: 'USD',
As we have a Price class, why don't make a Currency class, to ensure type safety and get cool getters like
etc
It's beyond the scope of Digital Ocean implementation, though it indeed is better to be done asap, it will be planned.
@ -0,0 +102,4 @@
Future<ServerVolume?> createVolume() async {
ServerVolume? volume;
final Response dbCreateResponse;
Quite counterintuitive to have a linal variable like this and have it reassigned later, but anyways.
maybe it should be a
createVolumeResponse
?@ -0,0 +118,4 @@
'filesystem_type': 'ext4',
},
);
final dbId = dbCreateResponse.data['volume']['id'];
db → volume
@ -0,0 +126,4 @@
name: dbName,
sizeByte: dbSize,
serverId: null,
linuxDevice: 'scsi-0DO_Volume_$dbName',
linuxDevice
is a full path!/dev/disk/by-id/scsi-0DO_Volume_$dbName
@ -0,0 +154,4 @@
final List<dynamic> rawVolumes = dbGetResponse.data['volumes'];
int id = 0;
for (final rawVolume in rawVolumes) {
final dbId = rawVolume['id'];
Same as before, do not forget to rename every
db
in var names and fix linuxDevice@ -0,0 +178,4 @@
}
Future<ServerVolume?> getVolume(final String volumeUuid) async {
ServerVolume? neededVolume;
requestedVolume
?@ -0,0 +195,4 @@
Future<void> deleteVolume(final ServerVolume volume) async {
final Dio client = await getClient();
try {
await client.delete('/volumes/$volume.uuid');
You are not acessing uuid here. '/volumes/${volume.uuid}' must be used.
@ -0,0 +450,4 @@
return server.copyWith(startTime: DateTime.now());
}
/// Digital Ocean returns a map of lists of /proc/state values,
It is
/proc/stat
, notstate
.@ -0,0 +500,4 @@
const int step = 15;
final Dio client = await getClient();
//try {
commented try block?
@ -0,0 +572,4 @@
metadata = [
ServerMetadataEntity(
type: MetadataType.id,
name: 'server.server_id'.tr(),
.tr() should be called by UI layer.
Will be a part of coming refactoring for business logic layer. Consider it a stub
@ -0,0 +653,4 @@
return servers;
}
String? getEmojiFlag(final String query) {
I guess it shouldn't be here. Wouldn't the one function for all providers be better?
While I understand that DO has its own declarations for every flag, we might make it a .fromDigitalOceanSlug constructor on some location enum.
Will be a part of coming refactoring for business logic layer. Consider it a stub
@ -373,3 +408,3 @@
if (!success) {
await Future.delayed(const Duration(seconds: 10));
await deleteVolume(dbId);
await deleteVolume(dataBase);
dataBase...
@ -26,0 +54,4 @@
/// Actual provider name to render on information page for user,
/// for example 'Digital Ocean' for Digital Ocean
String get appearanceProviderName;
displayName
@ -80,2 +83,4 @@
hetzner,
@HiveField(2)
digitalOcean,
}
Example of a factory:
@ -0,0 +5,4 @@
});
double value;
String currency;
Currency should be a smart enum.
It's beyond the scope of Digital Ocean implementation, though it indeed is better to be done asap, it will be planned.
@ -2,2 +2,4 @@
class _TextDetails extends StatelessWidget {
final Map<MetadataType, IconData> metadataToIcon = const {
MetadataType.id: Icons.numbers_outlined,
Move these icons to the MetadataType enum, so we can access them as
metadata.type.icon
The enum would look like this: