]>
Commit | Line | Data |
---|---|---|
565bbc73 DM |
1 | package PVE::APIClient::Commands::remote; |
2 | ||
3 | use strict; | |
4 | use warnings; | |
5 | ||
b4007425 | 6 | use PVE::APIClient::Helpers; |
c9138c03 | 7 | use PVE::APIClient::JSONSchema qw(get_standard_option); |
ca3269f4 | 8 | use PVE::APIClient::Tools qw(extract_param); |
3454a319 DM |
9 | use PVE::APIClient::Config; |
10 | ||
c9138c03 | 11 | use PVE::APIClient::CLIHandler; |
565bbc73 | 12 | |
2d0ebe21 | 13 | use PVE::APIClient::LWP; |
c9138c03 | 14 | use PVE::APIClient::PTY; |
2d0ebe21 | 15 | |
c9138c03 | 16 | use base qw(PVE::APIClient::CLIHandler); |
565bbc73 | 17 | |
2d0ebe21 | 18 | sub read_password { |
b2123baa | 19 | return PVE::APIClient::PTY::read_password("Remote password: ") |
2d0ebe21 RJ |
20 | } |
21 | ||
5101e472 DM |
22 | # define as array to keep ordering |
23 | my $remote_list_returns_properties = [ | |
24 | name => get_standard_option('pveclient-remote-name'), | |
25 | host => { type => 'string', format => 'address' }, | |
26 | username => { type => 'string' }, | |
27 | port => { type => 'integer', optional => 1 }, | |
28 | fingerprint => { type => 'string', optional => 1 }, | |
29 | ]; | |
30 | ||
e2ca543c | 31 | __PACKAGE__->register_method ({ |
e3468666 DM |
32 | name => 'remote_list', |
33 | path => 'remote_list', | |
e2ca543c RJ |
34 | method => 'GET', |
35 | description => "List remotes from your config file.", | |
36 | parameters => { | |
37 | additionalProperties => 0, | |
5101e472 | 38 | properties => { |
faa47c20 | 39 | 'format' => get_standard_option('pve-output-format'), |
5101e472 DM |
40 | }, |
41 | }, | |
42 | returns => { | |
43 | type => 'array', | |
44 | items => { | |
45 | type => 'object', | |
46 | properties => { @$remote_list_returns_properties }, | |
47 | }, | |
e2ca543c | 48 | }, |
e2ca543c | 49 | code => sub { |
5101e472 DM |
50 | my ($param) = @_; |
51 | ||
52 | my $format = PVE::APIClient::Tools::extract_param($param, 'format'); | |
53 | PVE::APIClient::Helpers::set_output_format($format); | |
54 | ||
69aa81b3 | 55 | my $config = PVE::APIClient::Config->load(); |
e2ca543c | 56 | |
5101e472 | 57 | my $res = []; |
69aa81b3 | 58 | for my $name (keys %{$config->{ids}}) { |
a6dab5b8 DM |
59 | my $data = $config->{ids}->{$name}; |
60 | next if $data->{type} ne 'remote'; | |
5101e472 | 61 | push @$res, $data; |
e2ca543c RJ |
62 | } |
63 | ||
5101e472 | 64 | return $res; |
e2ca543c RJ |
65 | }}); |
66 | ||
565bbc73 | 67 | __PACKAGE__->register_method ({ |
e3468666 DM |
68 | name => 'remote_add', |
69 | path => 'remote_add', | |
565bbc73 DM |
70 | method => 'POST', |
71 | description => "Add a remote to your config file.", | |
a6dab5b8 | 72 | parameters => PVE::APIClient::RemoteConfig->createSchema(1), |
565bbc73 DM |
73 | returns => { type => 'null'}, |
74 | code => sub { | |
75 | my ($param) = @_; | |
76 | ||
69aa81b3 DM |
77 | my $remote = $param->{name}; |
78 | ||
b4007425 | 79 | # Note: we try to keep lock time sort, and lock later when we have all info |
69aa81b3 DM |
80 | my $config = PVE::APIClient::Config->load(); |
81 | ||
82 | die "Remote '$remote' already exists\n" | |
83 | if $config->{ids}->{$remote}; | |
2d0ebe21 RJ |
84 | |
85 | my $last_fp = 0; | |
69aa81b3 | 86 | |
8842464b DM |
87 | my $password = $param->{password}; |
88 | if (!defined($password)) { | |
b2123baa | 89 | $password = PVE::APIClient::PTY::read_password("Remote password: "); |
8842464b DM |
90 | } |
91 | ||
69aa81b3 | 92 | my $setup = { |
2d0ebe21 | 93 | username => $param->{username}, |
8842464b | 94 | password => $password, |
2d0ebe21 RJ |
95 | host => $param->{host}, |
96 | port => $param->{port} // 8006, | |
69aa81b3 DM |
97 | }; |
98 | ||
99 | if ($param->{fingerprint}) { | |
100 | $setup->{cached_fingerprints} = { | |
101 | $param->{fingerprint} => 1, | |
102 | }; | |
103 | } else { | |
104 | $setup->{manual_verification} = 1; | |
105 | $setup->{register_fingerprint_cb} = sub { | |
106 | my $fp = shift @_; | |
107 | $last_fp = $fp; | |
108 | }; | |
109 | } | |
110 | ||
a304c3d7 | 111 | my $api = PVE::APIClient::LWP->new(%$setup); |
2d0ebe21 RJ |
112 | $api->login(); |
113 | ||
69aa81b3 | 114 | $param->{fingerprint} = $last_fp if !defined($param->{fingerprint}); |
b4007425 | 115 | |
69aa81b3 | 116 | my $plugin = PVE::APIClient::Config->lookup('remote'); |
69aa81b3 | 117 | |
b4007425 DM |
118 | my $code = sub { |
119 | ||
120 | $config = PVE::APIClient::Config->load(); # reload | |
121 | ||
122 | # check again (file is locked now) | |
123 | die "Remote '$remote' already exists\n" | |
124 | if $config->{ids}->{$remote}; | |
125 | ||
126 | my $opts = $plugin->check_config($remote, $param, 1, 1); | |
127 | ||
128 | $config->{ids}->{$remote} = $opts; | |
129 | ||
130 | PVE::APIClient::Config->save($config); | |
131 | }; | |
132 | ||
133 | PVE::APIClient::Config->lock_config(undef, $code); | |
69aa81b3 DM |
134 | |
135 | return undef; | |
136 | }}); | |
137 | ||
138 | __PACKAGE__->register_method ({ | |
e3468666 DM |
139 | name => 'remote_set', |
140 | path => 'remote_set', | |
69aa81b3 DM |
141 | method => 'PUT', |
142 | description => "Update a remote configuration.", | |
a6dab5b8 | 143 | parameters => PVE::APIClient::RemoteConfig->updateSchema(1), |
69aa81b3 DM |
144 | returns => { type => 'null'}, |
145 | code => sub { | |
146 | my ($param) = @_; | |
147 | ||
69aa81b3 DM |
148 | my $name = extract_param($param, 'name'); |
149 | my $digest = extract_param($param, 'digest'); | |
150 | my $delete = extract_param($param, 'delete'); | |
151 | ||
b4007425 DM |
152 | my $code = sub { |
153 | my $config = PVE::APIClient::Config->load(); | |
154 | my $remote = PVE::APIClient::Config->lookup_remote($config, $name); | |
69aa81b3 | 155 | |
b4007425 DM |
156 | my $plugin = PVE::APIClient::Config->lookup('remote'); |
157 | my $opts = $plugin->check_config($name, $param, 0, 1); | |
69aa81b3 | 158 | |
b4007425 DM |
159 | foreach my $k (%$opts) { |
160 | $remote->{$k} = $opts->{$k}; | |
161 | } | |
69aa81b3 | 162 | |
b4007425 DM |
163 | if ($delete) { |
164 | my $options = $plugin->private()->{options}->{'remote'}; | |
165 | foreach my $k (PVE::APIClient::Tools::APIClient::split_list($delete)) { | |
166 | my $d = $options->{$k} || | |
167 | die "no such option '$k'\n"; | |
168 | die "unable to delete required option '$k'\n" | |
169 | if !$d->{optional}; | |
170 | die "unable to delete fixed option '$k'\n" | |
171 | if $d->{fixed}; | |
172 | delete $remote->{$k}; | |
173 | } | |
69aa81b3 | 174 | } |
69aa81b3 | 175 | |
b4007425 DM |
176 | PVE::APIClient::Config->save($config); |
177 | }; | |
178 | ||
179 | PVE::APIClient::Config->lock_config(undef, $code); | |
565bbc73 | 180 | |
2d0ebe21 | 181 | return undef; |
565bbc73 DM |
182 | }}); |
183 | ||
184 | __PACKAGE__->register_method ({ | |
e3468666 DM |
185 | name => 'remote_delete', |
186 | path => 'remote_delete', | |
565bbc73 DM |
187 | method => 'DELETE', |
188 | description => "Removes a remote from your config file.", | |
189 | parameters => { | |
190 | additionalProperties => 0, | |
191 | properties => { | |
3454a319 | 192 | name => get_standard_option('pveclient-remote-name'), |
565bbc73 DM |
193 | }, |
194 | }, | |
195 | returns => { type => 'null'}, | |
196 | code => sub { | |
197 | my ($param) = @_; | |
198 | ||
b4007425 DM |
199 | my $code = sub { |
200 | my $config = PVE::APIClient::Config->load(); | |
201 | delete $config->{ids}->{$param->{name}}; | |
202 | PVE::APIClient::Config->save($config); | |
203 | }; | |
69aa81b3 | 204 | |
b4007425 | 205 | PVE::APIClient::Config->lock_config(undef, $code); |
565bbc73 | 206 | |
f79acf69 | 207 | return undef; |
565bbc73 DM |
208 | }}); |
209 | ||
210 | our $cmddef = { | |
e3468666 DM |
211 | add => [ __PACKAGE__, 'remote_add', ['name', 'host', 'username']], |
212 | set => [ __PACKAGE__, 'remote_set', ['name']], | |
213 | delete => [ __PACKAGE__, 'remote_delete', ['name']], | |
5101e472 DM |
214 | list => [__PACKAGE__, 'remote_list', undef, {}, sub { |
215 | PVE::APIClient::Helpers::print_ordered_result($remote_list_returns_properties, @_); | |
216 | }], | |
565bbc73 DM |
217 | }; |
218 | ||
219 | 1; |