api: acme plugins: we're not the storage content API endpoint

Drop various leftovers from the storage content API module this was
based on, e.g., ACME plugins have no fixed options and the like.
Also, the descriptions shouldn't mention "storage".

Further, drop the "update_config" "helper" with its operations
effectively only increasing code complexity and adding another rabbit
hole to jump into.

IF, this should have been factoring out the lock+read+write cycle
only, living the rest to a passed CODE-ref, but honestly that saves
only really the read and write config lines, and at this point
nothing is really gained, so just let it be.

Should have been actually three or so separate patches, but to deep
into this rabbit hole to care..

Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
This commit is contained in:
Thomas Lamprecht 2020-05-03 15:22:48 +02:00
parent 3c194d9e46
commit b1bc9372ec

View File

@ -6,20 +6,21 @@ use warnings;
use MIME::Base64;
use Storable qw(dclone);
use PVE::ACME::Challenge;
use PVE::ACME::DNSChallenge;
use PVE::ACME::StandAlone;
use PVE::Cluster qw(cfs_read_file cfs_write_file cfs_register_file);
use PVE::Cluster qw(cfs_read_file cfs_write_file cfs_register_file cfs_lock_file);
use PVE::JSONSchema qw(register_standard_option get_standard_option);
use PVE::Tools qw(extract_param);
use base qw(PVE::RESTHandler);
my $FILENAME = "priv/acme/plugins.cfg";
my $plugin_config_file = "priv/acme/plugins.cfg";
cfs_register_file ($FILENAME,
cfs_register_file($plugin_config_file,
sub { PVE::ACME::Challenge->parse_config(@_); },
sub { PVE::ACME::Challenge->write_config(@_); });
sub { PVE::ACME::Challenge->write_config(@_); },
);
PVE::ACME::DNSChallenge->register();
PVE::ACME::StandAlone->register();
@ -36,8 +37,7 @@ my $plugin_type_enum = PVE::ACME::Challenge->lookup_types();
my $modify_cfg_for_api = sub {
my ($cfg, $pluginid) = @_;
die "ACME plugin '$pluginid' not defined\n"
if !defined($cfg->{ids}->{$pluginid});
die "ACME plugin '$pluginid' not defined\n" if !defined($cfg->{ids}->{$pluginid});
my $plugin_cfg = dclone($cfg->{ids}->{$pluginid});
$plugin_cfg->{plugin} = $pluginid;
@ -59,7 +59,7 @@ __PACKAGE__->register_method ({
additionalProperties => 0,
properties => {
type => {
description => "Only list storage of specific type",
description => "Only list ACME plugins of a specific type",
type => 'string',
enum => $plugin_type_enum,
optional => 1,
@ -81,8 +81,7 @@ __PACKAGE__->register_method ({
my $cfg = load_config();
my $res =[];
my $res = [];
foreach my $pluginid (keys %{$cfg->{ids}}) {
my $plugin_cfg = $modify_cfg_for_api->($cfg, $pluginid);
next if $param->{type} && $param->{type} ne $plugin_cfg->{type};
@ -90,14 +89,14 @@ __PACKAGE__->register_method ({
}
return $res;
}});
}
});
__PACKAGE__->register_method({
name => 'get_plugin_config',
path => '{id}',
method => 'GET',
description => "Get ACME DNS plugin configuration.",
description => "Get ACME plugin configuration.",
permissions => {
check => ['perm', '/', [ 'Sys.Modify' ]],
},
@ -114,109 +113,104 @@ __PACKAGE__->register_method({
code => sub {
my ($param) = @_;
return $modify_cfg_for_api->(load_config(), $param->{id});
}});
my $update_config = sub {
my ($id, $op, $type, $param) = @_;
my $cfg = load_config();
if ( $op eq "add" ) {
die "Section with ID: $id already exists\n"
if defined($cfg->{ids}->{$id});
my $plugin = PVE::ACME::Challenge->lookup($type);
my $opts = $plugin->check_config($id, $param, 1, 1);
$cfg->{ids}->{$id} = $opts;
$cfg->{ids}->{$id}->{type} = $type;
} elsif ($op eq "update") {
die "Section with ID; $id does not exist\n"
if !defined($cfg->{ids}->{$id});
my $delete = extract_param($param, 'delete');
$type = $cfg->{ids}->{$id}->{type};
my $plugin = PVE::ACME::Challenge->lookup($type);
my $opts = $plugin->check_config($id, $param, 0, 1);
if ($delete) {
my $options = $plugin->private()->{options}->{$type};
foreach my $k (PVE::Tools::split_list($delete)) {
my $d = $options->{$k} || die "no such option '$k'\n";
die "unable to delete required option '$k'\n" if !$d->{optional};
die "unable to delete fixed option '$k'\n" if $d->{fixed};
die "cannot set and delete property '$k' at the same time!\n"
if defined($opts->{$k});
delete $cfg->{ids}->{$id}->{$k};
return $modify_cfg_for_api->($cfg, $param->{id});
}
}
for my $k (keys %$opts) {
print "$k: $opts->{$k}\n";
$cfg->{ids}->{$id}->{$k} = $opts->{$k};
}
} elsif ($op eq "del") {
delete $cfg->{ids}->{$id};
} else {
die 'undefined config update operation\n' if !defined($op);
die "unknown config update operation '$op'\n";
}
PVE::Cluster::cfs_write_file($FILENAME, $cfg);
};
});
__PACKAGE__->register_method({
name => 'add_plugin',
path => '',
method => 'POST',
description => "Add ACME DNS plugin configuration.",
description => "Add ACME plugin configuration.",
permissions => {
check => ['perm', '/', [ 'Sys.Modify' ]],
},
protected => 1,
parameters => PVE::ACME::Challenge->createSchema(),
returns => { type => "null" },
returns => {
type => "null"
},
code => sub {
my ($param) = @_;
my $id = extract_param($param, 'id');
my $type = extract_param($param, 'type');
PVE::Cluster::cfs_lock_file($FILENAME, undef, $update_config, $id, "add", $type, $param);
cfs_lock_file($plugin_config_file, undef, sub {
my $cfg = load_config();
die "ACME plugin ID '$id' already exists\n" if defined($cfg->{ids}->{$id});
my $plugin = PVE::ACME::Challenge->lookup($type);
my $opts = $plugin->check_config($id, $param, 1, 1);
$cfg->{ids}->{$id} = $opts;
$cfg->{ids}->{$id}->{type} = $type;
cfs_write_file($plugin_config_file, $cfg);
});
die "$@" if $@;
return undef;
}});
}
});
__PACKAGE__->register_method({
name => 'update_plugin',
path => '{id}',
method => 'PUT',
description => "Update ACME DNS plugin configuration.",
description => "Update ACME plugin configuration.",
permissions => {
check => ['perm', '/', [ 'Sys.Modify' ]],
},
protected => 1,
parameters => PVE::ACME::Challenge->updateSchema(),
returns => { type => "null" },
returns => {
type => "null"
},
code => sub {
my ($param) = @_;
my $id = extract_param($param, 'id');
my $delete = extract_param($param, 'delete');
PVE::Cluster::cfs_lock_file($FILENAME, undef, $update_config, $id, "update", undef, $param);
cfs_lock_file($plugin_config_file, undef, sub {
my $cfg = load_config();
my $plugin_cfg = $cfg->{ids}->{$id};
die "ACME plugin ID '$id' does not exist\n" if !$plugin_cfg;
my $type = $plugin_cfg->{type};
my $plugin = PVE::ACME::Challenge->lookup($type);
if (defined($delete)) {
my $schema = $plugin->private();
my $options = $schema->{options}->{$type};
for my $k (PVE::Tools::split_list($delete)) {
my $d = $options->{$k} || die "no such option '$k'\n";
die "unable to delete required option '$k'\n" if !$d->{optional};
delete $cfg->{ids}->{$id}->{$k};
}
}
my $opts = $plugin->check_config($id, $param, 0, 1);
for my $k (sort keys %$opts) {
$plugin_cfg->{$k} = $opts->{$k};
}
cfs_write_file($plugin_config_file, $cfg);
});
die "$@" if $@;
return undef;
}});
}
});
__PACKAGE__->register_method({
name => 'delete_plugin',
path => '{id}',
method => 'DELETE',
description => "Delete ACME DNS plugin configuration.",
description => "Delete ACME plugin configuration.",
permissions => {
check => ['perm', '/', [ 'Sys.Modify' ]],
},
@ -227,29 +221,31 @@ __PACKAGE__->register_method({
id => get_standard_option('pve-acme-pluginid'),
},
},
returns => { type => "null" },
returns => {
type => "null"
},
code => sub {
my ($param) = @_;
my $id = extract_param($param, 'id');
PVE::Cluster::cfs_lock_file($FILENAME, undef, $update_config, $id, "del", undef, $param );
cfs_lock_file($plugin_config_file, undef, sub {
my $cfg = load_config();
delete $cfg->{ids}->{$id};
cfs_write_file($plugin_config_file, $cfg);
});
die "$@" if $@;
return undef;
}});
}
});
sub load_config {
my $raw = eval { cfs_read_file($FILENAME) };
return $raw || {};
}
sub write_conf {
my ($conf) = @_;
my $raw = PVE::ACME::Challenge->write_config($FILENAME, $conf);
cfs_write_file($FILENAME, $raw);
my $cfg = {};
$cfg = cfs_read_file($plugin_config_file) if -e "/etc/pve/$plugin_config_file";
return $cfg;
}
1;