]>
Commit | Line | Data |
---|---|---|
a31c7b27 DM |
1 | package PVE::APIClient::Config; |
2 | ||
3 | use strict; | |
4 | use warnings; | |
5 | use JSON; | |
a31c7b27 | 6 | |
c9138c03 DM |
7 | use PVE::APIClient::JSONSchema; |
8 | use PVE::APIClient::SectionConfig; | |
269f8ffa | 9 | use PVE::APIClient::PTY; |
ca3269f4 | 10 | use PVE::APIClient::Tools qw(file_get_contents file_set_contents); |
a31c7b27 | 11 | |
c9138c03 | 12 | use base qw(PVE::APIClient::SectionConfig); |
69aa81b3 | 13 | |
a6dab5b8 DM |
14 | my $remote_namne_regex = qw(\w+); |
15 | ||
16 | my $defaults_section = '!DEFAULTS'; | |
17 | ||
184877d4 DM |
18 | my $complete_remote_name = sub { |
19 | ||
69aa81b3 | 20 | my $config = PVE::APIClient::Config->load(); |
a6dab5b8 DM |
21 | my $list = []; |
22 | foreach my $name (keys %{$config->{ids}}) { | |
23 | push @$list, $name if $name ne $defaults_section; | |
24 | } | |
25 | return $list; | |
184877d4 DM |
26 | }; |
27 | ||
cbfba90b DM |
28 | PVE::APIClient::JSONSchema::register_standard_option('pveclient-output-format', { |
29 | type => 'string', | |
30 | description => 'Output format.', | |
31 | enum => [ 'table', 'json' ], | |
32 | optional => 1, | |
33 | default => 'table', | |
34 | }); | |
35 | ||
c9138c03 | 36 | PVE::APIClient::JSONSchema::register_standard_option('pveclient-remote-name', { |
184877d4 DM |
37 | description => "The name of the remote.", |
38 | type => 'string', | |
a6dab5b8 | 39 | pattern => $remote_namne_regex, |
184877d4 DM |
40 | completion => $complete_remote_name, |
41 | }); | |
42 | ||
69aa81b3 DM |
43 | my $defaultData = { |
44 | propertyList => { | |
45 | type => { | |
46 | description => "Section type.", | |
47 | optional => 1, | |
48 | }, | |
69aa81b3 DM |
49 | }, |
50 | }; | |
06039c7f | 51 | |
69aa81b3 DM |
52 | sub private { |
53 | return $defaultData; | |
06039c7f | 54 | } |
aa570b38 | 55 | |
69aa81b3 DM |
56 | sub config_filename { |
57 | my ($class) = @_; | |
aa570b38 | 58 | |
aa5833d6 DM |
59 | my $home = $ENV{HOME}; |
60 | ||
61 | die "environment HOME not set\n" if !defined($home); | |
62 | ||
63 | return "$home/.pveclient"; | |
06039c7f | 64 | } |
aa570b38 | 65 | |
a6dab5b8 DM |
66 | sub format_section_header { |
67 | my ($class, $type, $sectionId, $scfg, $done_hash) = @_; | |
68 | ||
69 | if ($type eq 'defaults') { | |
70 | return "defaults:\n"; | |
71 | } else { | |
72 | return "$type: $sectionId\n"; | |
73 | } | |
74 | } | |
75 | ||
76 | sub parse_section_header { | |
77 | my ($class, $line) = @_; | |
78 | ||
79 | if ($line =~ m/^defaults:\s*$/) { | |
80 | return ('defaults', $defaults_section, undef, {}); | |
81 | } elsif ($line =~ m/^(\S+):\s*(\S+)\s*$/) { | |
82 | my ($type, $name) = (lc($1), $2); | |
83 | eval { | |
84 | die "invalid remote name '$name'\n" | |
85 | if $name eq $defaults_section || $name !~ m/^$remote_namne_regex$/; | |
86 | }; | |
87 | return ($type, $name, $@, {}); | |
88 | } | |
89 | return undef; | |
90 | } | |
91 | ||
69aa81b3 DM |
92 | sub load { |
93 | my ($class) = @_; | |
06039c7f | 94 | |
69aa81b3 | 95 | my $filename = $class->config_filename(); |
aa570b38 | 96 | |
69aa81b3 | 97 | my $raw = ''; |
06039c7f | 98 | |
69aa81b3 DM |
99 | if (-e $filename) { |
100 | my $filemode = (stat($filename))[2] & 07777; | |
101 | if ($filemode != 0600) { | |
102 | die sprintf "wrong permissions on '$filename' %04o (expected 0600)\n", $filemode; | |
103 | } | |
06039c7f | 104 | |
69aa81b3 DM |
105 | $raw = file_get_contents($filename); |
106 | } | |
06039c7f | 107 | |
69aa81b3 DM |
108 | return $class->parse_config($filename, $raw); |
109 | } | |
06039c7f | 110 | |
69aa81b3 DM |
111 | sub save { |
112 | my ($class, $cfg) = @_; | |
06039c7f | 113 | |
69aa81b3 | 114 | my $filename = $class->config_filename(); |
a6dab5b8 DM |
115 | |
116 | $cfg->{order}->{$defaults_section} = -1; # write as first section | |
69aa81b3 | 117 | my $raw = $class->write_config($filename, $cfg); |
06039c7f | 118 | |
69aa81b3 | 119 | file_set_contents($filename, $raw, 0600); |
06039c7f RJ |
120 | } |
121 | ||
a6dab5b8 DM |
122 | sub get_defaults { |
123 | my ($class, $cfg) = @_; | |
124 | ||
125 | $cfg->{ids}->{$defaults_section} //= {}; | |
126 | ||
127 | return $cfg->{ids}->{$defaults_section}; | |
128 | } | |
129 | ||
69aa81b3 DM |
130 | sub lookup_remote { |
131 | my ($class, $cfg, $name, $noerr) = @_; | |
06039c7f | 132 | |
69aa81b3 | 133 | my $data = $cfg->{ids}->{$name}; |
06039c7f | 134 | |
69aa81b3 | 135 | return $data if $noerr || defined($data); |
06039c7f | 136 | |
69aa81b3 | 137 | die "unknown remote \"$name\"\n"; |
06039c7f RJ |
138 | } |
139 | ||
140 | sub remote_conn { | |
69aa81b3 | 141 | my ($class, $cfg, $remote) = @_; |
06039c7f | 142 | |
69aa81b3 | 143 | my $section = $class->lookup_remote($cfg, $remote); |
8842464b DM |
144 | |
145 | my $password = $section->{password}; | |
146 | if (!defined($password)) { | |
269f8ffa | 147 | $password = PVE::APIClient::PTY::read_password("Remote password: ") |
8842464b DM |
148 | } |
149 | ||
06039c7f RJ |
150 | my $conn = PVE::APIClient::LWP->new( |
151 | username => $section->{username}, | |
8842464b | 152 | password => $password, |
06039c7f | 153 | host => $section->{host}, |
8842464b | 154 | port => $section->{port} // 8006, |
06039c7f RJ |
155 | cached_fingerprints => { |
156 | $section->{fingerprint} => 1, | |
157 | } | |
158 | ); | |
aa570b38 | 159 | |
06039c7f | 160 | $conn->login; |
aa570b38 | 161 | |
06039c7f | 162 | return $conn; |
aa570b38 | 163 | } |
a31c7b27 | 164 | |
a6dab5b8 DM |
165 | package PVE::APIClient::RemoteConfig; |
166 | ||
167 | use strict; | |
168 | use warnings; | |
169 | ||
c9138c03 DM |
170 | use PVE::APIClient::JSONSchema qw(register_standard_option get_standard_option); |
171 | use PVE::APIClient::SectionConfig; | |
a6dab5b8 DM |
172 | |
173 | use base qw( PVE::APIClient::Config); | |
174 | ||
175 | sub type { | |
176 | return 'remote'; | |
177 | } | |
178 | ||
179 | sub properties { | |
180 | return { | |
181 | name => get_standard_option('pveclient-remote-name'), | |
182 | host => { | |
183 | description => "The host.", | |
184 | type => 'string', format => 'address', | |
185 | optional => 1, | |
186 | }, | |
187 | username => { | |
188 | description => "The username.", | |
189 | type => 'string', | |
190 | optional => 1, | |
191 | }, | |
192 | password => { | |
193 | description => "The users password.", | |
194 | type => 'string', | |
195 | optional => 1, | |
196 | }, | |
197 | port => { | |
198 | description => "The port.", | |
199 | type => 'integer', | |
200 | optional => 1, | |
201 | default => 8006, | |
202 | }, | |
203 | fingerprint => { | |
204 | description => "Fingerprint.", | |
205 | type => 'string', | |
206 | optional => 1, | |
207 | }, | |
208 | comment => { | |
209 | description => "Description.", | |
210 | type => 'string', | |
211 | optional => 1, | |
212 | maxLength => 4096, | |
213 | }, | |
214 | }; | |
215 | } | |
216 | ||
217 | sub options { | |
218 | return { | |
219 | name => { optional => 0 }, | |
220 | host => { optional => 0 }, | |
221 | comment => { optional => 1 }, | |
222 | username => { optional => 0 }, | |
223 | password => { optional => 1 }, | |
224 | port => { optional => 1 }, | |
225 | fingerprint => { optional => 1 }, | |
226 | }; | |
227 | } | |
228 | ||
229 | __PACKAGE__->register(); | |
230 | ||
231 | ||
232 | package PVE::APIClient::DefaultsConfig; | |
233 | ||
234 | use strict; | |
235 | use warnings; | |
236 | ||
c9138c03 | 237 | use PVE::APIClient::JSONSchema qw(register_standard_option get_standard_option); |
a6dab5b8 DM |
238 | |
239 | use base qw( PVE::APIClient::Config); | |
240 | ||
241 | ||
242 | sub type { | |
243 | return 'defaults'; | |
244 | } | |
245 | ||
246 | sub options { | |
247 | return { | |
248 | name => { optional => 1 }, | |
249 | username => { optional => 1 }, | |
250 | port => { optional => 1 }, | |
251 | }; | |
252 | } | |
253 | ||
69aa81b3 | 254 | __PACKAGE__->register(); |
a6dab5b8 DM |
255 | |
256 | ||
257 | PVE::APIClient::Config->init(); | |
69aa81b3 | 258 | |
a31c7b27 | 259 | 1; |