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