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