mirror of
https://github.com/oddlama/nix-config.git
synced 2025-10-11 07:10:39 +02:00
feat: add influxdb provisioning module
This commit is contained in:
parent
37f77eed3d
commit
16c9d8bb5e
1 changed files with 826 additions and 0 deletions
826
modules/meta/influxdb.nix
Normal file
826
modules/meta/influxdb.nix
Normal file
|
@ -0,0 +1,826 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
inherit
|
||||
(lib)
|
||||
concatMap
|
||||
concatMapStrings
|
||||
count
|
||||
elem
|
||||
escapeShellArg
|
||||
escapeShellArgs
|
||||
filter
|
||||
flip
|
||||
genAttrs
|
||||
getExe
|
||||
hasAttr
|
||||
head
|
||||
mkBefore
|
||||
mkEnableOption
|
||||
mkIf
|
||||
mkOption
|
||||
optional
|
||||
optionalString
|
||||
optionals
|
||||
types
|
||||
unique
|
||||
;
|
||||
|
||||
cfg = config.services.influxdb2;
|
||||
in {
|
||||
options.services.influxdb2 = {
|
||||
initialSetup = {
|
||||
enable = mkEnableOption "initial database setup";
|
||||
organization = mkOption {
|
||||
type = types.str;
|
||||
example = "main";
|
||||
description = "Primary organization name";
|
||||
};
|
||||
bucket = mkOption {
|
||||
type = types.str;
|
||||
example = "example";
|
||||
description = "Primary bucket name";
|
||||
};
|
||||
username = mkOption {
|
||||
type = types.str;
|
||||
default = "admin";
|
||||
description = "Primary username";
|
||||
};
|
||||
retention = mkOption {
|
||||
type = types.str;
|
||||
default = "0";
|
||||
description = ''
|
||||
The duration for which the bucket will retain data (0 is infinite).
|
||||
Accepted units are `ns` (nanoseconds), `us` or `µs` (microseconds), `ms` (milliseconds),
|
||||
`s` (seconds), `m` (minutes), `h` (hours), `d` (days) and `w` (weeks).
|
||||
'';
|
||||
};
|
||||
passwordFile = mkOption {
|
||||
type = types.path;
|
||||
description = "Password for primary user. Don't use a file from the nix store!";
|
||||
};
|
||||
tokenFile = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
default = null;
|
||||
description = "API Token for the admin user. If not given, influx will automatically generate one.";
|
||||
};
|
||||
};
|
||||
|
||||
deleteOrganizations = mkOption {
|
||||
description = "List of organizations that should be deleted.";
|
||||
default = [];
|
||||
type = types.listOf types.str;
|
||||
};
|
||||
|
||||
deleteBuckets = mkOption {
|
||||
description = "List of buckets that should be deleted.";
|
||||
default = [];
|
||||
type = types.listOf (types.submodule {
|
||||
options.name = mkOption {
|
||||
description = "Name of the bucket.";
|
||||
type = types.str;
|
||||
};
|
||||
|
||||
options.org = mkOption {
|
||||
description = "The organization to which the bucket belongs.";
|
||||
type = types.str;
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
deleteUsers = mkOption {
|
||||
description = "List of users that should be deleted.";
|
||||
default = [];
|
||||
type = types.listOf types.str;
|
||||
};
|
||||
|
||||
deleteRemotes = mkOption {
|
||||
description = "List of remotes that should be deleted.";
|
||||
default = [];
|
||||
type = types.listOf (types.submodule {
|
||||
options.name = mkOption {
|
||||
description = "Name of the remote.";
|
||||
type = types.str;
|
||||
};
|
||||
|
||||
options.org = mkOption {
|
||||
description = "The organization to which the remote belongs.";
|
||||
type = types.str;
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
deleteReplications = mkOption {
|
||||
description = "List of replications that should be deleted.";
|
||||
default = [];
|
||||
type = types.listOf (types.submodule {
|
||||
options.name = mkOption {
|
||||
description = "Name of the replication.";
|
||||
type = types.str;
|
||||
};
|
||||
|
||||
options.org = mkOption {
|
||||
description = "The organization to which the replication belongs.";
|
||||
type = types.str;
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
deleteApiTokens = mkOption {
|
||||
description = "List of api tokens that should be deleted.";
|
||||
default = [];
|
||||
type = types.listOf (types.submodule ({config, ...}: {
|
||||
options.id = mkOption {
|
||||
description = "A unique identifier for this token. See `ensureApiTokens.*.name` for more information.";
|
||||
readOnly = true;
|
||||
default = builtins.substring 0 32 (builtins.hashString "sha256" "${config.user}:${config.org}:${config.name}");
|
||||
type = types.str;
|
||||
};
|
||||
|
||||
options.name = mkOption {
|
||||
description = "Name of the api token.";
|
||||
type = types.str;
|
||||
};
|
||||
|
||||
options.org = mkOption {
|
||||
description = "The organization to which the api token belongs.";
|
||||
type = types.str;
|
||||
};
|
||||
|
||||
options.user = mkOption {
|
||||
description = "The user to which the api token belongs.";
|
||||
type = types.str;
|
||||
};
|
||||
}));
|
||||
};
|
||||
|
||||
ensureOrganizations = mkOption {
|
||||
description = "List of organizations that should be created. Future changes to the name will not be reflected.";
|
||||
default = [];
|
||||
type = types.listOf (types.submodule {
|
||||
options.name = mkOption {
|
||||
description = "Name of the organization.";
|
||||
type = types.str;
|
||||
};
|
||||
|
||||
options.description = mkOption {
|
||||
description = "Optional description for the organization.";
|
||||
default = null;
|
||||
type = types.nullOr types.str;
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
ensureBuckets = mkOption {
|
||||
description = "List of buckets that should be created. Future changes to the name or org will not be reflected.";
|
||||
default = [];
|
||||
type = types.listOf (types.submodule {
|
||||
options.name = mkOption {
|
||||
description = "Name of the bucket.";
|
||||
type = types.str;
|
||||
};
|
||||
|
||||
options.org = mkOption {
|
||||
description = "The organization the bucket belongs to.";
|
||||
type = types.str;
|
||||
};
|
||||
|
||||
options.description = mkOption {
|
||||
description = "Optional description for the bucket.";
|
||||
default = null;
|
||||
type = types.nullOr types.str;
|
||||
};
|
||||
|
||||
options.retention = mkOption {
|
||||
type = types.str;
|
||||
default = "0";
|
||||
description = ''
|
||||
The duration for which the bucket will retain data (0 is infinite).
|
||||
Accepted units are `ns` (nanoseconds), `us` or `µs` (microseconds), `ms` (milliseconds),
|
||||
`s` (seconds), `m` (minutes), `h` (hours), `d` (days) and `w` (weeks).
|
||||
'';
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
ensureUsers = mkOption {
|
||||
description = "List of users that should be created. Future changes to the name or primary org will not be reflected.";
|
||||
default = [];
|
||||
type = types.listOf (types.submodule {
|
||||
options.name = mkOption {
|
||||
description = "Name of the user.";
|
||||
type = types.str;
|
||||
};
|
||||
|
||||
options.org = mkOption {
|
||||
description = "Primary organization to which the user will be added as a member.";
|
||||
type = types.str;
|
||||
};
|
||||
|
||||
options.passwordFile = mkOption {
|
||||
description = "Password for the user. If unset, the user will not be able to log in until a password is set by an operator! Don't use a file from the nix store!";
|
||||
type = types.nullOr types.path;
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
ensureRemotes = mkOption {
|
||||
description = "List of remotes that should be created. Future changes to the name, org or remoteOrg will not be reflected.";
|
||||
default = [];
|
||||
type = types.listOf (types.submodule {
|
||||
options.name = mkOption {
|
||||
description = "Name of the remote.";
|
||||
type = types.str;
|
||||
};
|
||||
|
||||
options.org = mkOption {
|
||||
description = "Organization to which the remote belongs.";
|
||||
type = types.str;
|
||||
};
|
||||
|
||||
options.description = mkOption {
|
||||
description = "Optional description for the remote.";
|
||||
default = null;
|
||||
type = types.nullOr types.str;
|
||||
};
|
||||
|
||||
options.remoteUrl = mkOption {
|
||||
description = "The url where the remote instance can be reached";
|
||||
type = types.str;
|
||||
};
|
||||
|
||||
options.remoteOrg = mkOption {
|
||||
description = ''
|
||||
Corresponding remote organization. If this is used instead of `remoteOrgId`,
|
||||
the remote organization id must be queried first which means the provided remote
|
||||
token must have the `read-orgs` flag.
|
||||
'';
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
};
|
||||
|
||||
options.remoteOrgId = mkOption {
|
||||
description = "Corresponding remote organization id.";
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
};
|
||||
|
||||
options.remoteTokenFile = mkOption {
|
||||
type = types.path;
|
||||
description = "API token used to authenticate with the remote.";
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
ensureReplications = mkOption {
|
||||
description = "List of replications that should be created. Future changes to name, org or buckets will not be reflected.";
|
||||
default = [];
|
||||
type = types.listOf (types.submodule {
|
||||
options.name = mkOption {
|
||||
description = "Name of the remote.";
|
||||
type = types.str;
|
||||
};
|
||||
|
||||
options.org = mkOption {
|
||||
description = "Organization to which the replication belongs.";
|
||||
type = types.str;
|
||||
};
|
||||
|
||||
options.remote = mkOption {
|
||||
description = "The remote to replicate to.";
|
||||
type = types.str;
|
||||
};
|
||||
|
||||
options.localBucket = mkOption {
|
||||
description = "The local bucket to replicate from.";
|
||||
type = types.str;
|
||||
};
|
||||
|
||||
options.remoteBucket = mkOption {
|
||||
description = "The remte bucket to replicate to.";
|
||||
type = types.str;
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
ensureApiTokens = mkOption {
|
||||
description = "List of api tokens that should be created. Future changes to existing tokens cannot be reflected.";
|
||||
default = [];
|
||||
type = types.listOf (types.submodule ({config, ...}: {
|
||||
options.id = mkOption {
|
||||
description = "A unique identifier for this token. Since influx doesn't store names for tokens, this will be hashed and appended to the description to identify the token.";
|
||||
readOnly = true;
|
||||
default = builtins.substring 0 32 (builtins.hashString "sha256" "${config.user}:${config.org}:${config.name}");
|
||||
type = types.str;
|
||||
};
|
||||
|
||||
options.name = mkOption {
|
||||
description = "A name to identify this token. Not an actual influxdb attribute, but needed to calculate a stable id (see `id`).";
|
||||
type = types.str;
|
||||
};
|
||||
|
||||
options.user = mkOption {
|
||||
description = "The user to which the token belongs.";
|
||||
type = types.str;
|
||||
};
|
||||
|
||||
options.org = mkOption {
|
||||
description = "Organization to which the token belongs.";
|
||||
type = types.str;
|
||||
};
|
||||
|
||||
options.description = mkOption {
|
||||
description = ''
|
||||
Optional description for the api token.
|
||||
Note that the actual token will always be created with a description regardless
|
||||
of whether this is given or not. A unique suffix has to be appended to later identify
|
||||
the token to track whether it has already been created.
|
||||
'';
|
||||
default = null;
|
||||
type = types.nullOr types.str;
|
||||
};
|
||||
|
||||
options.operator = mkOption {
|
||||
description = "Grants all permissions in all organizations.";
|
||||
default = false;
|
||||
type = types.bool;
|
||||
};
|
||||
|
||||
options.allAccess = mkOption {
|
||||
description = "Grants all permissions in the associated organization.";
|
||||
default = false;
|
||||
type = types.bool;
|
||||
};
|
||||
|
||||
options.readPermissions = mkOption {
|
||||
description = ''
|
||||
The read permissions to include for this token. Access is usually granted only
|
||||
for resources in the associated organization.
|
||||
|
||||
Available permissions are `authorizations`, `buckets`, `dashboards`,
|
||||
`orgs`, `tasks`, `telegrafs`, `users`, `variables`, `secrets`, `labels`, `views`,
|
||||
`documents`, `notificationRules`, `notificationEndpoints`, `checks`, `dbrp`,
|
||||
`annotations`, `sources`, `scrapers`, `notebooks`, `remotes`, `replications`.
|
||||
|
||||
Refer to `influx auth create --help` for a full list with descriptions.
|
||||
|
||||
`buckets` grants read access to all associated buckets. Use `readBuckets` to define
|
||||
more granular access permissions.
|
||||
'';
|
||||
default = [];
|
||||
type = types.listOf types.str;
|
||||
};
|
||||
|
||||
options.writePermissions = mkOption {
|
||||
description = ''
|
||||
The read permissions to include for this token. Access is usually granted only
|
||||
for resources in the associated organization.
|
||||
|
||||
Available permissions are `authorizations`, `buckets`, `dashboards`,
|
||||
`orgs`, `tasks`, `telegrafs`, `users`, `variables`, `secrets`, `labels`, `views`,
|
||||
`documents`, `notificationRules`, `notificationEndpoints`, `checks`, `dbrp`,
|
||||
`annotations`, `sources`, `scrapers`, `notebooks`, `remotes`, `replications`.
|
||||
|
||||
Refer to `influx auth create --help` for a full list with descriptions.
|
||||
|
||||
`buckets` grants write access to all associated buckets. Use `writeBuckets` to define
|
||||
more granular access permissions.
|
||||
'';
|
||||
default = [];
|
||||
type = types.listOf types.str;
|
||||
};
|
||||
|
||||
options.readBuckets = mkOption {
|
||||
description = "The organization's buckets which should be allowed to be read";
|
||||
default = [];
|
||||
type = types.listOf types.str;
|
||||
};
|
||||
|
||||
options.writeBuckets = mkOption {
|
||||
description = "The organization's buckets which should be allowed to be written";
|
||||
default = [];
|
||||
type = types.listOf types.str;
|
||||
};
|
||||
}));
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf (cfg.enable && cfg.initialSetup.enable) {
|
||||
assertions = let
|
||||
validPermissions = flip genAttrs (x: true) [
|
||||
"authorizations"
|
||||
"buckets"
|
||||
"dashboards"
|
||||
"orgs"
|
||||
"tasks"
|
||||
"telegrafs"
|
||||
"users"
|
||||
"variables"
|
||||
"secrets"
|
||||
"labels"
|
||||
"views"
|
||||
"documents"
|
||||
"notificationRules"
|
||||
"notificationEndpoints"
|
||||
"checks"
|
||||
"dbrp"
|
||||
"annotations"
|
||||
"sources"
|
||||
"scrapers"
|
||||
"notebooks"
|
||||
"remotes"
|
||||
"replications"
|
||||
];
|
||||
|
||||
knownOrgs = map (x: x.name) cfg.ensureOrganizations;
|
||||
knownRemotes = map (x: x.name) cfg.ensureRemotes;
|
||||
knownBucketsFor = org: map (x: x.name) (filter (x: x.org == org) cfg.ensureBuckets);
|
||||
in
|
||||
flip concatMap cfg.ensureBuckets (bucket: [
|
||||
{
|
||||
assertion = elem bucket.org knownOrgs;
|
||||
message = "The influxdb bucket '${bucket.name}' refers to an unknown organization '${bucket.org}'.";
|
||||
}
|
||||
])
|
||||
++ flip concatMap cfg.ensureUsers (user: [
|
||||
{
|
||||
assertion = elem user.org knownOrgs;
|
||||
message = "The influxdb user '${user.name}' refers to an unknown organization '${user.org}'.";
|
||||
}
|
||||
])
|
||||
++ flip concatMap cfg.ensureRemotes (remote: [
|
||||
{
|
||||
assertion = (remote.remoteOrgId == null) != (remote.remoteOrg == null);
|
||||
message = "The influxdb remote '${remote.name}' must specify exactly one of remoteOrgId or remoteOrg.";
|
||||
}
|
||||
{
|
||||
assertion = elem remote.org knownOrgs;
|
||||
message = "The influxdb remote '${remote.name}' refers to an unknown organization '${remote.org}'.";
|
||||
}
|
||||
])
|
||||
++ flip concatMap cfg.ensureReplications (replication: [
|
||||
{
|
||||
assertion = elem replication.remote knownRemotes;
|
||||
message = "The influxdb replication '${replication.name}' refers to an unknown remote '${replication.remote}'.";
|
||||
}
|
||||
(let
|
||||
remote = head (filter (x: x.name == replication.remote) cfg.ensureRemotes);
|
||||
in {
|
||||
assertion = elem replication.localBucket (knownBucketsFor remote.org);
|
||||
message = "The influxdb replication '${replication.name}' refers to an unknown bucket '${replication.localBucket}' in organization '${remote.org}'.";
|
||||
})
|
||||
])
|
||||
++ flip concatMap cfg.ensureApiTokens (apiToken: let
|
||||
validBuckets = flip genAttrs (x: true) (knownBucketsFor apiToken.org);
|
||||
in [
|
||||
{
|
||||
assertion = elem apiToken.org knownOrgs;
|
||||
message = "The influxdb apiToken '${apiToken.name}' refers to an unknown organization '${apiToken.org}'.";
|
||||
}
|
||||
{
|
||||
assertion =
|
||||
1
|
||||
== count (x: x) [
|
||||
apiToken.operator
|
||||
apiToken.allAccess
|
||||
(apiToken.readPermissions
|
||||
!= []
|
||||
|| apiToken.writePermissions != []
|
||||
|| apiToken.readBuckets != []
|
||||
|| apiToken.writeBuckets != [])
|
||||
];
|
||||
message = "The influxdb apiToken '${apiToken.name}' in organization '${apiToken.org}' uses mutually exclusive options. The `operator` and `allAccess` options are mutually exclusive with each other and the granular permission settings.";
|
||||
}
|
||||
(let
|
||||
unknownBuckets = filter (x: !hasAttr x validBuckets) apiToken.readBuckets;
|
||||
in {
|
||||
assertion = unknownBuckets == [];
|
||||
message = "The influxdb apiToken '${apiToken.name}' refers to invalid buckets in readBuckets: ${toString unknownBuckets}";
|
||||
})
|
||||
(let
|
||||
unknownBuckets = filter (x: !hasAttr x validBuckets) apiToken.writeBuckets;
|
||||
in {
|
||||
assertion = unknownBuckets == [];
|
||||
message = "The influxdb apiToken '${apiToken.name}' refers to invalid buckets in writeBuckets: ${toString unknownBuckets}";
|
||||
})
|
||||
(let
|
||||
unknownPerms = filter (x: !hasAttr x validPermissions) apiToken.readPermissions;
|
||||
in {
|
||||
assertion = unknownPerms == [];
|
||||
message = "The influxdb apiToken '${apiToken.name}' refers to invalid read permissions: ${toString unknownPerms}";
|
||||
})
|
||||
(let
|
||||
unknownPerms = filter (x: !hasAttr x validPermissions) apiToken.writePermissions;
|
||||
in {
|
||||
assertion = unknownPerms == [];
|
||||
message = "The influxdb apiToken '${apiToken.name}' refers to invalid write permissions: ${toString unknownPerms}";
|
||||
})
|
||||
]);
|
||||
|
||||
systemd.services.influxdb2 = {
|
||||
# Mark if this is the first startup so postStart can do the initial setup
|
||||
preStart = ''
|
||||
if ! test -e "$STATE_DIRECTORY/influxd.bolt"; then
|
||||
touch "$STATE_DIRECTORY/.first_startup"
|
||||
fi
|
||||
'';
|
||||
|
||||
postStart = let
|
||||
influxCli = "${pkgs.influxdb2-cli}/bin/influx"; # getExe pkgs.influxdb2-cli
|
||||
in
|
||||
''
|
||||
set -euo pipefail
|
||||
export INFLUX_HOST="http://"${escapeShellArg config.services.influxdb2.settings.http-bind-address}
|
||||
|
||||
# Wait for the influxdb server to come online
|
||||
count=0
|
||||
while ! ${influxCli} ping &>/dev/null; do
|
||||
if [ "$count" -eq 300 ]; then
|
||||
echo "Tried for 30 seconds, giving up..."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! kill -0 "$MAINPID"; then
|
||||
echo "Main server died, giving up..."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
sleep 0.1
|
||||
count=$((count++))
|
||||
done
|
||||
|
||||
if test -e "$STATE_DIRECTORY/.first_startup"; then
|
||||
# Do the initial database setup. Pass /dev/null as configs-path to
|
||||
# avoid saving the token as the active config.
|
||||
${influxCli} setup \
|
||||
--configs-path /dev/null \
|
||||
--org ${escapeShellArg cfg.initialSetup.organization} \
|
||||
--bucket ${escapeShellArg cfg.initialSetup.bucket} \
|
||||
--username ${escapeShellArg cfg.initialSetup.username} \
|
||||
--password "$(< ${escapeShellArg cfg.initialSetup.passwordFile})" \
|
||||
--token "$(< ${escapeShellArg cfg.initialSetup.tokenFile})" \
|
||||
--retention ${escapeShellArg cfg.initialSetup.retention} \
|
||||
--force >/dev/null
|
||||
|
||||
rm -f "$STATE_DIRECTORY/.first_startup"
|
||||
fi
|
||||
|
||||
export INFLUX_TOKEN=$(< ${escapeShellArg cfg.initialSetup.tokenFile})
|
||||
''
|
||||
+ flip concatMapStrings cfg.deleteApiTokens (apiToken: ''
|
||||
if id=$(
|
||||
${influxCli} auth list --json --org ${escapeShellArg apiToken.org} 2>/dev/null \
|
||||
| ${getExe pkgs.jq} -r '.[] | select(.description | contains("${apiToken.id}")) | .id'
|
||||
) && [[ -n "$id" ]]; then
|
||||
${influxCli} auth delete --id "$id" &>/dev/null
|
||||
echo "Deleted api token id="${escapeShellArg apiToken.id}
|
||||
fi
|
||||
'')
|
||||
+ flip concatMapStrings cfg.deleteReplications (replication: ''
|
||||
if id=$(
|
||||
${influxCli} replication list --json --org ${escapeShellArg replication.org} --name ${escapeShellArg replication.name} 2>/dev/null \
|
||||
| ${getExe pkgs.jq} -r ".[0].id"
|
||||
); then
|
||||
${influxCli} replication delete --id "$id" &>/dev/null
|
||||
echo "Deleted replication org="${escapeShellArg replication.org}" name="${escapeShellArg replication.name}
|
||||
fi
|
||||
'')
|
||||
+ flip concatMapStrings cfg.deleteRemotes (remote: ''
|
||||
if id=$(
|
||||
${influxCli} remote list --json --org ${escapeShellArg remote.org} --name ${escapeShellArg remote.name} 2>/dev/null \
|
||||
| ${getExe pkgs.jq} -r ".[0].id"
|
||||
); then
|
||||
${influxCli} remote delete --id "$id" &>/dev/null
|
||||
echo "Deleted remote org="${escapeShellArg remote.org}" name="${escapeShellArg remote.name}
|
||||
fi
|
||||
'')
|
||||
+ flip concatMapStrings cfg.deleteUsers (user: ''
|
||||
if id=$(
|
||||
${influxCli} user list --json --name ${escapeShellArg user} 2>/dev/null \
|
||||
| ${getExe pkgs.jq} -r ".[0].id"
|
||||
); then
|
||||
${influxCli} user delete --id "$id" &>/dev/null
|
||||
echo "Deleted user name="${escapeShellArg user}
|
||||
fi
|
||||
'')
|
||||
+ flip concatMapStrings cfg.deleteBuckets (bucket: ''
|
||||
if id=$(
|
||||
${influxCli} bucket list --json --org ${escapeShellArg bucket.org} --name ${escapeShellArg bucket.name} 2>/dev/null \
|
||||
| ${getExe pkgs.jq} -r ".[0].id"
|
||||
); then
|
||||
${influxCli} bucket delete --id "$id" &>/dev/null
|
||||
echo "Deleted bucket org="${escapeShellArg bucket.org}" name="${escapeShellArg bucket.name}
|
||||
fi
|
||||
'')
|
||||
+ flip concatMapStrings cfg.deleteOrganizations (org: ''
|
||||
if id=$(
|
||||
${influxCli} org list --json --name ${escapeShellArg org} 2>/dev/null \
|
||||
| ${getExe pkgs.jq} -r ".[0].id"
|
||||
); then
|
||||
${influxCli} org delete --id "$id" &>/dev/null
|
||||
echo "Deleted org name="${escapeShellArg org}
|
||||
fi
|
||||
'')
|
||||
+ flip concatMapStrings cfg.ensureOrganizations (org: let
|
||||
listArgs = [
|
||||
"--name"
|
||||
org.name
|
||||
];
|
||||
updateArgs = optionals (org.description != null) [
|
||||
"--description"
|
||||
org.description
|
||||
];
|
||||
createArgs = listArgs ++ updateArgs;
|
||||
in ''
|
||||
if id=$(
|
||||
${influxCli} org list --json ${escapeShellArgs listArgs} 2>/dev/null \
|
||||
| ${getExe pkgs.jq} -r ".[0].id"
|
||||
); then
|
||||
${influxCli} org update --id "$id" ${escapeShellArgs updateArgs} &>/dev/null
|
||||
else
|
||||
${influxCli} org create ${escapeShellArgs createArgs} &>/dev/null
|
||||
echo "Created org name="${escapeShellArg org.name}
|
||||
fi
|
||||
'')
|
||||
+ flip concatMapStrings cfg.ensureBuckets (bucket: let
|
||||
listArgs = [
|
||||
"--org"
|
||||
bucket.org
|
||||
"--name"
|
||||
bucket.name
|
||||
];
|
||||
updateArgs =
|
||||
[
|
||||
"--retention"
|
||||
bucket.retention
|
||||
]
|
||||
++ optionals (bucket.description != null) [
|
||||
"--description"
|
||||
bucket.description
|
||||
];
|
||||
createArgs = listArgs ++ updateArgs;
|
||||
in ''
|
||||
if id=$(
|
||||
${influxCli} bucket list --json ${escapeShellArgs listArgs} 2>/dev/null \
|
||||
| ${getExe pkgs.jq} -r ".[0].id"
|
||||
); then
|
||||
${influxCli} bucket update --id "$id" ${escapeShellArgs updateArgs} &>/dev/null
|
||||
else
|
||||
${influxCli} bucket create ${escapeShellArgs createArgs} &>/dev/null
|
||||
echo "Created bucket org="${escapeShellArg bucket.org}" name="${escapeShellArg bucket.name}
|
||||
fi
|
||||
'')
|
||||
+ flip concatMapStrings cfg.ensureUsers (user: let
|
||||
listArgs = [
|
||||
"--name"
|
||||
user.name
|
||||
];
|
||||
createArgs =
|
||||
listArgs
|
||||
++ [
|
||||
"--org"
|
||||
user.org
|
||||
];
|
||||
in
|
||||
''
|
||||
if id=$(
|
||||
${influxCli} user list --json ${escapeShellArgs listArgs} 2>/dev/null \
|
||||
| ${getExe pkgs.jq} -r ".[0].id"
|
||||
); then
|
||||
true # No updateable args
|
||||
else
|
||||
${influxCli} user create ${escapeShellArgs createArgs} &>/dev/null
|
||||
echo "Created user name="${escapeShellArg user.name}
|
||||
fi
|
||||
''
|
||||
+ optionalString (user.passwordFile != null) ''
|
||||
${influxCli} user password ${escapeShellArgs listArgs} \
|
||||
--password "$(< ${escapeShellArg user.passwordFile})" &>/dev/null
|
||||
'')
|
||||
+ flip concatMapStrings cfg.ensureRemotes (remote: let
|
||||
listArgs = [
|
||||
"--name"
|
||||
remote.name
|
||||
"--org"
|
||||
remote.org
|
||||
];
|
||||
updateArgs =
|
||||
[
|
||||
"--remote-url"
|
||||
remote.remoteUrl
|
||||
]
|
||||
++ optionals (remote.remoteOrgId != null) [
|
||||
"--remote-org-id"
|
||||
remote.remoteOrgId
|
||||
]
|
||||
++ optionals (remote.description != null) [
|
||||
"--description"
|
||||
remote.description
|
||||
];
|
||||
createArgs = listArgs ++ updateArgs;
|
||||
in ''
|
||||
if id=$(
|
||||
${influxCli} remote list --json ${escapeShellArgs listArgs} 2>/dev/null \
|
||||
| ${getExe pkgs.jq} -r ".[0].id"
|
||||
); then
|
||||
${influxCli} remote update --id "$id" ${escapeShellArgs updateArgs} &>/dev/null \
|
||||
--remote-api-token "$(< ${escapeShellArg remote.remoteTokenFile})"
|
||||
else
|
||||
extraArgs=()
|
||||
${optionalString (remote.remoteOrg != null) ''
|
||||
remote_org_id=$(
|
||||
${influxCli} org list --json \
|
||||
--host ${escapeShellArg remote.remoteUrl} \
|
||||
--token "$(< ${escapeShellArg remote.remoteTokenFile})" \
|
||||
--name ${escapeShellArg remote.remoteOrg} 2>/dev/null \
|
||||
| ${getExe pkgs.jq} -r ".[0].id"
|
||||
)
|
||||
extraArgs+=("--remote-org-id" "$remote_org_id")
|
||||
''}
|
||||
${influxCli} remote create ${escapeShellArgs createArgs} &>/dev/null \
|
||||
--remote-api-token "$(< ${escapeShellArg remote.remoteTokenFile})" \
|
||||
"''${extraArgs[@]}"
|
||||
echo "Created remote org="${escapeShellArg remote.org}" name="${escapeShellArg remote.name}
|
||||
fi
|
||||
'')
|
||||
+ flip concatMapStrings cfg.ensureReplications (replication: let
|
||||
listArgs = [
|
||||
"--name"
|
||||
replication.name
|
||||
"--org"
|
||||
replication.org
|
||||
];
|
||||
createArgs =
|
||||
listArgs
|
||||
++ [
|
||||
"--local-bucket"
|
||||
replication.localBucket
|
||||
"--remote-bucket"
|
||||
replication.remoteBucket
|
||||
];
|
||||
in ''
|
||||
if id=$(
|
||||
${influxCli} replication list --json ${escapeShellArgs listArgs} 2>/dev/null \
|
||||
| ${getExe pkgs.jq} -r ".[0].id"
|
||||
); then
|
||||
true # No updateable args
|
||||
else
|
||||
remote_id=$(
|
||||
${influxCli} remote list --json --name ${escapeShellArg replication.remote} 2>/dev/null \
|
||||
| ${getExe pkgs.jq} -r ".[0].id"
|
||||
)
|
||||
${influxCli} replication create ${escapeShellArgs createArgs} &>/dev/null \
|
||||
--remote-id "$remote_id"
|
||||
echo "Created replication org="${escapeShellArg replication.org}" name="${escapeShellArg replication.name}
|
||||
fi
|
||||
'')
|
||||
+ flip concatMapStrings cfg.ensureApiTokens (apiToken: let
|
||||
listArgs = [
|
||||
"--user"
|
||||
apiToken.user
|
||||
"--org"
|
||||
apiToken.org
|
||||
];
|
||||
createArgs =
|
||||
listArgs
|
||||
++ [
|
||||
"--description"
|
||||
(optionalString (apiToken.description != null) "${apiToken.description} - " + apiToken.id)
|
||||
]
|
||||
++ optional apiToken.operator "--operator"
|
||||
++ optional apiToken.allAccess "--all-access"
|
||||
++ map (x: "--read-${x}") apiToken.readPermissions
|
||||
++ map (x: "--write-${x}") apiToken.writePermissions;
|
||||
in ''
|
||||
if id=$(
|
||||
${influxCli} apiToken list --json ${escapeShellArgs listArgs} 2>/dev/null \
|
||||
| ${getExe pkgs.jq} -r ".[0].id"
|
||||
); then
|
||||
true # No updateable args
|
||||
else
|
||||
declare -A bucketIds
|
||||
${flip concatMapStrings (unique (apiToken.readBuckets ++ apiToken.writeBuckets)) (bucket: ''
|
||||
bucketIds[${escapeShellArg bucket}]=$(
|
||||
${influxCli} bucket list --json --org ${escapeShellArg apiToken.org} --name ${escapeShellArg bucket} 2>/dev/null \
|
||||
| ${getExe pkgs.jq} -r ".[0].id"
|
||||
)
|
||||
'')}
|
||||
extraArgs=(
|
||||
${flip concatMapStrings apiToken.readBuckets (bucket: ''
|
||||
"--read-bucket" "''${bucketIds[${escapeShellArg bucket}]}"
|
||||
'')}
|
||||
${flip concatMapStrings apiToken.writeBuckets (bucket: ''
|
||||
"--write-bucket" "''${bucketIds[${escapeShellArg bucket}]}"
|
||||
'')}
|
||||
)
|
||||
${influxCli} auth create ${escapeShellArgs createArgs} &>/dev/null \
|
||||
"''${extraArgs[@]}"
|
||||
echo "Created api token org="${escapeShellArg apiToken.org}" user="${escapeShellArg apiToken.user}
|
||||
fi
|
||||
'');
|
||||
};
|
||||
};
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue