]> git.proxmox.com Git - pve-client.git/blame - PVE/APIClient/Config.pm
Config.pm: use PVE::APIClient::PTY
[pve-client.git] / PVE / APIClient / Config.pm
CommitLineData
a31c7b27
DM
1package PVE::APIClient::Config;
2
3use strict;
4use warnings;
5use JSON;
a31c7b27 6
c9138c03
DM
7use PVE::APIClient::JSONSchema;
8use PVE::APIClient::SectionConfig;
269f8ffa 9use PVE::APIClient::PTY;
ca3269f4 10use PVE::APIClient::Tools qw(file_get_contents file_set_contents);
a31c7b27 11
c9138c03 12use base qw(PVE::APIClient::SectionConfig);
69aa81b3 13
a6dab5b8
DM
14my $remote_namne_regex = qw(\w+);
15
16my $defaults_section = '!DEFAULTS';
17
184877d4
DM
18my $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
28PVE::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 36PVE::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
43my $defaultData = {
44 propertyList => {
45 type => {
46 description => "Section type.",
47 optional => 1,
48 },
69aa81b3
DM
49 },
50};
06039c7f 51
69aa81b3
DM
52sub private {
53 return $defaultData;
06039c7f 54}
aa570b38 55
69aa81b3
DM
56sub 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
66sub 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
76sub 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
92sub 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
111sub 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
122sub get_defaults {
123 my ($class, $cfg) = @_;
124
125 $cfg->{ids}->{$defaults_section} //= {};
126
127 return $cfg->{ids}->{$defaults_section};
128}
129
69aa81b3
DM
130sub 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
140sub 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
165package PVE::APIClient::RemoteConfig;
166
167use strict;
168use warnings;
169
c9138c03
DM
170use PVE::APIClient::JSONSchema qw(register_standard_option get_standard_option);
171use PVE::APIClient::SectionConfig;
a6dab5b8
DM
172
173use base qw( PVE::APIClient::Config);
174
175sub type {
176 return 'remote';
177}
178
179sub 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
217sub 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
232package PVE::APIClient::DefaultsConfig;
233
234use strict;
235use warnings;
236
c9138c03 237use PVE::APIClient::JSONSchema qw(register_standard_option get_standard_option);
a6dab5b8
DM
238
239use base qw( PVE::APIClient::Config);
240
241
242sub type {
243 return 'defaults';
244}
245
246sub 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
257PVE::APIClient::Config->init();
69aa81b3 258
a31c7b27 2591;