]>
Commit | Line | Data |
---|---|---|
29505e2c DM |
1 | package PVE::APIClient::Helpers; |
2 | ||
3 | use strict; | |
4 | use warnings; | |
5 | ||
ab79ce78 | 6 | use Storable; |
29505e2c DM |
7 | use JSON; |
8 | use PVE::APIClient::Exception qw(raise); | |
29505e2c DM |
9 | use Encode::Locale; |
10 | use Encode; | |
11 | use HTTP::Status qw(:constants); | |
12 | ||
13 | my $pve_api_definition; | |
14 | my $pve_api_path_hash; | |
15 | ||
ab79ce78 | 16 | my $pve_api_definition_fn = "/usr/share/pve-client/pve-api-definition.dat"; |
29505e2c DM |
17 | |
18 | my $build_pve_api_path_hash; | |
19 | $build_pve_api_path_hash = sub { | |
20 | my ($tree) = @_; | |
21 | ||
22 | my $class = ref($tree); | |
23 | return $tree if !$class; | |
24 | ||
25 | if ($class eq 'ARRAY') { | |
26 | foreach my $el (@$tree) { | |
27 | $build_pve_api_path_hash->($el); | |
28 | } | |
29 | } elsif ($class eq 'HASH') { | |
30 | if (defined($tree->{leaf}) && defined(my $path = $tree->{path})) { | |
31 | $pve_api_path_hash->{$path} = $tree; | |
32 | } | |
33 | foreach my $k (keys %$tree) { | |
34 | $build_pve_api_path_hash->($tree->{$k}); | |
35 | } | |
36 | } | |
37 | }; | |
38 | ||
39 | sub get_api_definition { | |
40 | ||
41 | if (!defined($pve_api_definition)) { | |
29505e2c DM |
42 | open(my $fh, '<', $pve_api_definition_fn) || |
43 | die "unable to open '$pve_api_definition_fn' - $!\n"; | |
ab79ce78 | 44 | $pve_api_definition = Storable::fd_retrieve($fh); |
29505e2c DM |
45 | $build_pve_api_path_hash->($pve_api_definition); |
46 | } | |
47 | ||
29505e2c DM |
48 | return $pve_api_definition; |
49 | } | |
50 | ||
51 | sub lookup_api_method { | |
635c0511 | 52 | my ($path, $method, $noerr) = @_; |
29505e2c DM |
53 | |
54 | get_api_definition(); # make sure API data is loaded | |
55 | ||
635c0511 DM |
56 | my $info = $pve_api_path_hash->{$path}; |
57 | ||
58 | if (!$info) { | |
59 | return undef if $noerr; | |
29505e2c | 60 | die "unable to find API info for path '$path'\n"; |
635c0511 | 61 | } |
29505e2c | 62 | |
635c0511 DM |
63 | my $data = $info->{info}->{$method}; |
64 | ||
65 | if (!$data) { | |
66 | return undef if $noerr; | |
29505e2c | 67 | die "unable to find API method '$method' for path '$path'\n"; |
635c0511 | 68 | } |
29505e2c DM |
69 | |
70 | return $data; | |
71 | } | |
72 | ||
635c0511 DM |
73 | sub complete_api_call_options { |
74 | my ($cmd, $prop, $prev, $cur, $args) = @_; | |
75 | ||
76 | my $print_result = sub { | |
77 | foreach my $p (@_) { | |
78 | print "$p\n" if $p =~ m/^$cur/; | |
79 | } | |
80 | }; | |
81 | ||
82 | my $print_parameter_completion = sub { | |
83 | my ($pname) = @_; | |
84 | my $d = $prop->{$pname}; | |
85 | if ($d->{completion}) { | |
86 | my $vt = ref($d->{completion}); | |
87 | if ($vt eq 'CODE') { | |
88 | my $res = $d->{completion}->($cmd, $pname, $cur, $args); | |
89 | &$print_result(@$res); | |
90 | } | |
91 | } elsif ($d->{type} eq 'boolean') { | |
92 | &$print_result('0', '1'); | |
93 | } elsif ($d->{enum}) { | |
94 | &$print_result(@{$d->{enum}}); | |
95 | } | |
96 | }; | |
97 | ||
98 | my @option_list = (); | |
99 | foreach my $key (keys %$prop) { | |
100 | push @option_list, "--$key"; | |
101 | } | |
102 | ||
103 | if ($cur =~ m/^-/) { | |
104 | &$print_result(@option_list); | |
105 | return; | |
106 | } | |
107 | ||
108 | if ($prev =~ m/^--?(.+)$/ && $prop->{$1}) { | |
109 | my $pname = $1; | |
110 | &$print_parameter_completion($pname); | |
111 | return; | |
112 | } | |
113 | ||
114 | &$print_result(@option_list); | |
115 | } | |
116 | ||
117 | sub complete_api_path { | |
118 | my ($text) = @_; | |
119 | ||
120 | get_api_definition(); # make sure API data is loaded | |
121 | ||
122 | $text =~ s!^/!!; | |
123 | ||
124 | my ($dir, $rest) = $text =~ m|^(?:(.*)/)?(?:([^/]*))?$|; | |
125 | ||
126 | my $info; | |
127 | if (!defined($dir)) { | |
128 | $dir = ''; | |
129 | $info = { children => $pve_api_definition }; | |
130 | } else { | |
131 | $info = $pve_api_path_hash->{"/$dir"}; | |
132 | } | |
133 | ||
134 | if ($info) { | |
135 | if (my $children = $info->{children}) { | |
136 | foreach my $c (@$children) { | |
137 | if ($c->{path} =~ m!\Q$dir/$rest!) { | |
138 | print "$c->{path}\n"; | |
139 | print "$c->{path}/\n"if $c->{children}; | |
140 | } | |
141 | } | |
142 | } | |
143 | } | |
144 | } | |
145 | ||
29505e2c | 146 | 1; |