Mohamed Abukar | 34e4383 | 2019-11-13 17:57:15 +0200 | [diff] [blame] | 1 | #!/usr/bin/perl -w |
Abukar Mohamed | 8504f6a | 2019-04-03 11:07:48 +0000 | [diff] [blame] | 2 | # |
| 3 | # Copyright (c) 2019 AT&T Intellectual Property. |
| 4 | # Copyright (c) 2019 Nokia. |
| 5 | # |
| 6 | # Licensed under the Apache License, Version 2.0 (the "License"); |
| 7 | # you may not use this file except in compliance with the License. |
| 8 | # You may obtain a copy of the License at |
| 9 | # |
| 10 | # http://www.apache.org/licenses/LICENSE-2.0 |
| 11 | # |
| 12 | # Unless required by applicable law or agreed to in writing, software |
| 13 | # distributed under the License is distributed on an "AS IS" BASIS, |
| 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 15 | # |
| 16 | # See the License for the specific language governing permissions and |
| 17 | # limitations under the License. |
| 18 | # |
| 19 | ############################# |
| 20 | # Simple cli for xapp manager |
| 21 | # |
Mohamed Abukar | 34e4383 | 2019-11-13 17:57:15 +0200 | [diff] [blame] | 22 | # In addition to standard shell tools, requires basic Perl installation |
| 23 | # (Ubuntu package "perl-base", installed by default), packages "curl" and |
Abukar Mohamed | 8504f6a | 2019-04-03 11:07:48 +0000 | [diff] [blame] | 24 | # "yajl-tools" (the second provides json_reformat on Ubuntu; on Red Hat-style |
| 25 | # distributions install "yajl" instead). |
| 26 | # |
Mohamed Abukar | 34e4383 | 2019-11-13 17:57:15 +0200 | [diff] [blame] | 27 | use strict; |
| 28 | use Getopt::Long; |
| 29 | use Fcntl; |
Abukar Mohamed | 8504f6a | 2019-04-03 11:07:48 +0000 | [diff] [blame] | 30 | |
Mohamed Abukar | 34e4383 | 2019-11-13 17:57:15 +0200 | [diff] [blame] | 31 | my $myname="appmgrcli"; |
| 32 | |
| 33 | sub usage { |
| 34 | print <<"EOF1"; |
| 35 | usage: $myname [-h host] [-p port] [-v] [-c curlprog] command params... |
| 36 | - command is deploy, undeploy, status, subscriptions, health, config, help |
Abukar Mohamed | 8504f6a | 2019-04-03 11:07:48 +0000 | [diff] [blame] | 37 | - (abbreviations dep, undep, stat, subs, heal allowed) |
| 38 | - Parameters of the commands that may have parameters: |
| 39 | -- deploy: name of the xapp to deploy |
Mohamed Abukar | 34e4383 | 2019-11-13 17:57:15 +0200 | [diff] [blame] | 40 | ---- Deployment parameters come from the Help chart but the following can be |
| 41 | ---- overridden by option with the same name (for example --configName=cname): |
| 42 | ----- helmVersion ReleaseName namespace podHost (host of pods). |
Abukar Mohamed | 8504f6a | 2019-04-03 11:07:48 +0000 | [diff] [blame] | 43 | -- undeploy: name of the xapp to undeploy |
| 44 | -- status: |
| 45 | ---- No parameters: Lists information about all deployed xapps |
| 46 | ---- xapp name as parameter: Prints information about the given xapp |
| 47 | ---- xapp name and instance: Lists information about the given instance only |
| 48 | -- subscriptions is followed by sub-command list, add, delete, or modify |
Mohamed Abukar | 34e4383 | 2019-11-13 17:57:15 +0200 | [diff] [blame] | 49 | --- (abbreviations del and mod for delete and modify are allowed): |
Abukar Mohamed | 8504f6a | 2019-04-03 11:07:48 +0000 | [diff] [blame] | 50 | ---- list without parameters lists all subscriptions |
| 51 | ---- list with subscription id prints that subscription |
| 52 | ---- add URL eventType maxRetry retryTimer |
| 53 | ------- URL is the URL to notify |
| 54 | ------- eventType one of created,deleted,all |
| 55 | ------- maxRetry and retryTimer are positive decimal numbers |
| 56 | ---- modify id URL eventType maxRetry retryTimer |
| 57 | ------- id is the subscription id (find out with the list command) |
| 58 | --------the rest of the parameters are like in add |
| 59 | ---- delete id |
| 60 | ------- id is the subscription id to delete (find out with the list command) |
Mohamed Abukar | 34e4383 | 2019-11-13 17:57:15 +0200 | [diff] [blame] | 61 | -- config is followed by sub-command list, add, delete, or modify |
| 62 | --- (abbreviations del and mod for delete and modify are allowed): |
| 63 | ---- list (no pars) |
| 64 | ------ lists the configuration of all xapps |
| 65 | ---- add jsonfile |
| 66 | ------ Creates xapp configuration. the jsonfile must contain all data (see API) |
| 67 | ---- add name configName namespace configSchemaFile configDataFile |
| 68 | ------ Creates xapp configuration, but unlike in the 1-parameter form, |
| 69 | ------ Xapp name, config map name and namespace are separate parameters. |
| 70 | ------ The other data come from JSON files. |
| 71 | ---- modify |
| 72 | ------ Modifies existing configuration. Same parameters (1 or 5) as in add. |
| 73 | ---- delete name configName namespace |
| 74 | ------ Deletes the configuration identified by the parameters. |
| 75 | -------------------------------------------------------------- |
Abukar Mohamed | 8504f6a | 2019-04-03 11:07:48 +0000 | [diff] [blame] | 76 | - Default values for host and port can be set in environment |
| 77 | - variables APPMGR_HOST and APPMGR_PORT |
| 78 | - Option -v sets verbose mode. |
Mohamed Abukar | 34e4383 | 2019-11-13 17:57:15 +0200 | [diff] [blame] | 79 | - Option -c overrides the used curl program name ("curl" by default). |
| 80 | - Exit code is 0 for success, 1 for any kind of failure. |
Abukar Mohamed | 8504f6a | 2019-04-03 11:07:48 +0000 | [diff] [blame] | 81 | EOF1 |
Mohamed Abukar | 34e4383 | 2019-11-13 17:57:15 +0200 | [diff] [blame] | 82 | exit 0; |
| 83 | } |
| 84 | |
| 85 | sub helphint { |
| 86 | print "run $myname help (or --help) for instructions\n"; |
Abukar Mohamed | 8504f6a | 2019-04-03 11:07:48 +0000 | [diff] [blame] | 87 | } |
| 88 | |
| 89 | # Defaults |
| 90 | |
Mohamed Abukar | 34e4383 | 2019-11-13 17:57:15 +0200 | [diff] [blame] | 91 | my $host="localhost"; |
| 92 | my $port=8080; |
| 93 | my $verbose=0; |
| 94 | my $showhelp = 0; |
| 95 | |
| 96 | # API URLs |
| 97 | |
| 98 | my $base="/ric/v1"; |
| 99 | my $base_xapps="$base/xapps"; |
| 100 | my $base_health="$base/health"; |
| 101 | my $base_subs="$base/subscriptions"; |
| 102 | my $base_config="$base/config"; |
Abukar Mohamed | 8504f6a | 2019-04-03 11:07:48 +0000 | [diff] [blame] | 103 | |
| 104 | # Check for environment override |
Mohamed Abukar | 34e4383 | 2019-11-13 17:57:15 +0200 | [diff] [blame] | 105 | if (exists $ENV{"APPMGR_HOST"}) { |
| 106 | $host=$ENV{"APPMGR_HOST"}; |
| 107 | } |
| 108 | if (exists $ENV{"APPMGR_PORT"}) { |
| 109 | $port=$ENV{"APPMGR_PORT"}; |
| 110 | } |
Abukar Mohamed | 8504f6a | 2019-04-03 11:07:48 +0000 | [diff] [blame] | 111 | |
Mohamed Abukar | 34e4383 | 2019-11-13 17:57:15 +0200 | [diff] [blame] | 112 | # Overrides for some deploy parameters |
Abukar Mohamed | 8504f6a | 2019-04-03 11:07:48 +0000 | [diff] [blame] | 113 | |
Mohamed Abukar | 34e4383 | 2019-11-13 17:57:15 +0200 | [diff] [blame] | 114 | my $configName = ""; |
| 115 | my $namespace = "ricxapp"; |
rangajal | 2a40997 | 2020-11-03 12:03:40 +0300 | [diff] [blame] | 116 | # Check for environment override |
| 117 | if (exists $ENV{"XAPP_NAMESPACE"}) { |
| 118 | $namespace=$ENV{"XAPP_NAMESPACE"}; |
| 119 | } |
Mohamed Abukar | 34e4383 | 2019-11-13 17:57:15 +0200 | [diff] [blame] | 120 | my $releaseName = ""; |
| 121 | my $helmVersion = "0.0.1"; |
| 122 | my $overrideFile = ""; |
| 123 | my $podHost = ""; |
Abukar Mohamed | 8504f6a | 2019-04-03 11:07:48 +0000 | [diff] [blame] | 124 | |
Mohamed Abukar | 34e4383 | 2019-11-13 17:57:15 +0200 | [diff] [blame] | 125 | # The curl command can be overridden for testing with a dummy. |
Abukar Mohamed | 8504f6a | 2019-04-03 11:07:48 +0000 | [diff] [blame] | 126 | |
Mohamed Abukar | 34e4383 | 2019-11-13 17:57:15 +0200 | [diff] [blame] | 127 | my $curl = "curl"; |
Abukar Mohamed | 8504f6a | 2019-04-03 11:07:48 +0000 | [diff] [blame] | 128 | |
Mohamed Abukar | 34e4383 | 2019-11-13 17:57:15 +0200 | [diff] [blame] | 129 | Getopt::Long::Configure("no_auto_abbrev", "permute"); |
| 130 | if (! GetOptions("h=s" => \$host, |
| 131 | "p=i" => \$port, |
| 132 | "c=s" => \$curl, |
| 133 | "ConfigName=s" => \$configName, |
| 134 | "Namespace=s" => \$namespace, |
| 135 | "ReleaseName=s" => \$releaseName, |
| 136 | "HelmVersion=s" => \$helmVersion, |
| 137 | "OverrideFile=s" => \$overrideFile, |
| 138 | "podHost=s" => \$podHost, |
| 139 | "help" => \$showhelp, |
| 140 | "v" => \$verbose)) { |
| 141 | print "$myname: Error in options\n"; |
| 142 | helphint(); |
| 143 | exit 1; |
| 144 | } |
Abukar Mohamed | 8504f6a | 2019-04-03 11:07:48 +0000 | [diff] [blame] | 145 | |
Mohamed Abukar | 34e4383 | 2019-11-13 17:57:15 +0200 | [diff] [blame] | 146 | if ($showhelp) { |
| 147 | usage(); |
| 148 | exit 0; |
| 149 | } |
| 150 | |
| 151 | if ($verbose) { |
| 152 | print "host = $host\n"; |
| 153 | print "port = $port\n"; |
| 154 | print "ConfigName = $configName\n"; |
| 155 | print "Namespace = $namespace\n"; |
| 156 | print "ReleaseName = $releaseName\n"; |
| 157 | print "HelmVersion = $helmVersion\n"; |
| 158 | print "OverrideFile = $overrideFile\n"; |
| 159 | print "podHost = $podHost\n"; |
| 160 | for (my $idx = 0; $idx <= $#ARGV; ++$idx) { |
| 161 | print "\$ARGV[$idx] = $ARGV[$idx]\n"; |
| 162 | } |
| 163 | } |
| 164 | |
| 165 | # Verify command and call handler function |
| 166 | |
| 167 | my %commands = ( |
| 168 | "deploy" => \&do_deploy, |
| 169 | "dep" => \&do_deploy, |
| 170 | "undeploy" => \&do_undeploy, |
| 171 | "undep" => \&do_undeploy, |
| 172 | "status" => \&do_status, |
| 173 | "stat" => \&do_status, |
| 174 | "subscriptions" => \&do_subscriptions, |
| 175 | "subs" => \&do_subscriptions, |
| 176 | "health" => \&do_health, |
| 177 | "heal" => \&do_health, |
| 178 | "config" => \&do_config, |
| 179 | "help" => \&usage |
| 180 | ); |
| 181 | |
| 182 | if ($#ARGV < 0) { |
| 183 | print "$myname: Missing command\n"; |
| 184 | helphint(); |
| 185 | exit 1; |
| 186 | } |
| 187 | |
Abukar Mohamed | 8504f6a | 2019-04-03 11:07:48 +0000 | [diff] [blame] | 188 | # Variable status used for the return value of the whole script. |
Mohamed Abukar | 34e4383 | 2019-11-13 17:57:15 +0200 | [diff] [blame] | 189 | my $status = 0; |
| 190 | |
| 191 | my $command = $ARGV[0]; |
| 192 | shift; |
| 193 | if (exists $commands{$command}) { |
| 194 | # Call the handler function with the rest of the command line |
| 195 | $commands{$command}(@ARGV); |
| 196 | exit $status; # Default exit. A handler can exit also if more convenient |
| 197 | } |
| 198 | print "$myname: Unrecognised command $command\n"; |
| 199 | helphint(); |
| 200 | exit 1; |
| 201 | |
| 202 | my $errfile; |
| 203 | my $resultfile; |
| 204 | |
| 205 | |
| 206 | sub make_temp_name($) { |
| 207 | my $tmpsuffix = "${$}${^T}"; |
| 208 | return "$_[0].$tmpsuffix"; |
| 209 | } |
| 210 | |
| 211 | sub make_temps { |
| 212 | $errfile = make_temp_name("/tmp/appmgr_e"); |
| 213 | $resultfile = make_temp_name("/tmp/appmgr_r"); |
| 214 | } |
| 215 | |
| 216 | sub remove_temps { |
| 217 | unlink ($errfile, $resultfile); |
| 218 | } |
| 219 | |
| 220 | sub print_file($$) { |
| 221 | my $outputhandle = $_[0]; |
| 222 | my $filename = $_[1]; |
| 223 | my $buffer; |
| 224 | my $inhandle; |
| 225 | if (!open($inhandle, "<", $filename)) { |
| 226 | print $outputhandle "$myname print_file: cannot open $filename: $!\n"; |
| 227 | return; |
| 228 | } |
| 229 | while (read($inhandle, $buffer, 4000) > 0) { |
| 230 | print $outputhandle $buffer; |
| 231 | } |
| 232 | close($inhandle); |
| 233 | } |
| 234 | |
| 235 | # The HTTP protocol result code, filled in by rest(). |
| 236 | |
| 237 | my $http_code = ""; |
| 238 | |
| 239 | # Helper: Given a curl output file, extract the number from ##code line. |
| 240 | # return ERROR if file cannot be opened, or "" if no code found. |
| 241 | |
| 242 | sub find_http_code($) { |
| 243 | my ($fh, $line, $code); |
| 244 | open($fh, "<", $_[0]) or return "ERROR"; |
| 245 | while ($line = <$fh>) { |
| 246 | if ($line =~ /^##([0-9]+)/) { |
| 247 | return $1; |
| 248 | } |
| 249 | } |
| 250 | return ""; |
| 251 | } |
Abukar Mohamed | 8504f6a | 2019-04-03 11:07:48 +0000 | [diff] [blame] | 252 | |
| 253 | # Helper for command execution: |
| 254 | # Do a rest call with "curl": $1 = method, $2 = path (without host and port |
| 255 | # which come from variables), $3 data to POST if needed |
Mohamed Abukar | 34e4383 | 2019-11-13 17:57:15 +0200 | [diff] [blame] | 256 | # returns true (1) if OK, and any returned data is in $resultfile |
| 257 | # else 0, and error message from curl is in $errfile, which is printed |
| 258 | # before returning the 0. |
Abukar Mohamed | 8504f6a | 2019-04-03 11:07:48 +0000 | [diff] [blame] | 259 | # |
| 260 | # On curl options: --silent --show-error disables progress bar, but allows |
| 261 | # error messages. --connect-timeout 20 limits waiting for connection to |
| 262 | # 20 seconds. In practice connection will succeed almost immediately, |
| 263 | # or in the case of wrong address not at all. |
Mohamed Abukar | 34e4383 | 2019-11-13 17:57:15 +0200 | [diff] [blame] | 264 | # To get the http code, using -w with format. The result comes at the end |
| 265 | # of the output, so "decorating" it for easier filtering. |
| 266 | # The code is put to global $http_code. |
Abukar Mohamed | 8504f6a | 2019-04-03 11:07:48 +0000 | [diff] [blame] | 267 | # |
Mohamed Abukar | 34e4383 | 2019-11-13 17:57:15 +0200 | [diff] [blame] | 268 | sub rest($$_) { |
| 269 | my $method = $_[0]; |
| 270 | my $path = $_[1]; |
| 271 | my $data = $_[2] || ""; |
| 272 | my $retval = 1; |
| 273 | my $http_status_file = make_temp_name("/tmp/appmgr_h"); |
Mohamed Abukar | b175b94 | 2019-05-09 16:30:58 +0300 | [diff] [blame] | 274 | |
Mohamed Abukar | 34e4383 | 2019-11-13 17:57:15 +0200 | [diff] [blame] | 275 | # This redirects stderr (fd 2) to $errfile, but saving normal stderr |
| 276 | # so that if can be restored. |
| 277 | open(OLDERR, ">&", \*STDERR) or die "Can't dup STDERR: $!"; |
| 278 | open(ERRFILE, ">", $errfile) or die "open errorfile failed"; |
| 279 | open(STDERR, ">&", \*ERRFILE) or die "Can't dup ERRFILE: $!"; |
| 280 | |
| 281 | # This redirects stdout (fd 1) to $http_status_file, but saving original |
| 282 | # so that if can be restored. |
| 283 | open(OLDSTDOUT, ">&", \*STDOUT) or die "Can't dup STDOUT: $!"; |
| 284 | open(HTTP_STATUS_FILE, ">", $http_status_file) or die "open http status file failed"; |
| 285 | open(STDOUT, ">&", \*HTTP_STATUS_FILE) or die "Can't dup HTTP_STATUS_FILE: $!"; |
| 286 | |
| 287 | my @args = ($curl, "--silent", "--show-error", "--connect-timeout", "20", |
| 288 | "--header", "Content-Type: application/json", "-X", $method, |
| 289 | "-o", $resultfile, "-w", '\n##%{http_code}\n', |
| 290 | "http://${host}:${port}${path}"); |
| 291 | if ($data ne "") { |
| 292 | push(@args, "--data"); |
| 293 | push(@args, $data); |
| 294 | } |
| 295 | if ($verbose) { |
| 296 | print OLDSTDOUT "Running: " . join(" ", @args) . "\n"; |
| 297 | } |
| 298 | if (system(@args) == -1) { |
| 299 | print OLDSTDOUT "$myname: failed to execute @args\n"; |
| 300 | $retval = 0; |
| 301 | } |
| 302 | elsif ($? & 127) { |
| 303 | printf OLDSTDOUT "$myname: child died with signal %d, %s coredump\n", |
| 304 | ($? & 127), ($? & 128) ? 'with' : 'without'; |
| 305 | $retval = 0; |
| 306 | } |
| 307 | else { |
| 308 | my $curl_exit_code = $? >> 8; |
| 309 | if ($curl_exit_code == 0) { |
| 310 | seek HTTP_STATUS_FILE, 0, 0; # Ensures flushing |
| 311 | $http_code = find_http_code($http_status_file); |
| 312 | if ($http_code eq "ERROR") { |
| 313 | print OLDSTDOUT "$myname: failed to open temp file $http_status_file\n"; |
| 314 | $retval = 0; |
| 315 | } |
| 316 | elsif ($http_code eq "") { |
| 317 | print OLDSTDOUT "$myname: curl failed to provide HTTP code\n"; |
| 318 | $retval = 0; |
| 319 | } |
| 320 | else { |
| 321 | if ($verbose) { |
| 322 | print OLDSTDOUT "HTTP status code = $http_code\n"; |
| 323 | } |
| 324 | $retval = 1; # Interaction OK from REST point of view |
| 325 | } |
| 326 | } |
| 327 | else { |
| 328 | print_file(\*OLDSTDOUT, $errfile); |
| 329 | $retval = 0; |
| 330 | } |
| 331 | } |
| 332 | open(STDOUT, ">&", \*OLDSTDOUT) or die "Can't dup OLDSTDOUT: $!"; |
| 333 | open(STDERR, ">&", \*OLDERR) or die "Can't dup OLDERR: $!"; |
| 334 | unlink($http_status_file); |
| 335 | return $retval; |
Abukar Mohamed | 8504f6a | 2019-04-03 11:07:48 +0000 | [diff] [blame] | 336 | } |
| 337 | |
Mohamed Abukar | 34e4383 | 2019-11-13 17:57:15 +0200 | [diff] [blame] | 338 | # Pretty-print a JSON file to stdout. |
| 339 | # (currently uses json_reformat command) |
| 340 | # Skips the ##httpcode line we make "curl" |
| 341 | # add in order to get access to the HTTP status. |
| 342 | |
| 343 | sub print_json($) { |
| 344 | my $filename = $_[0]; |
| 345 | my ($line, $inhandle, $outhandle); |
| 346 | if (!open($inhandle, "<", $filename)) { |
| 347 | print "$myname print_json: cannot open $filename: $!\n"; |
| 348 | return; |
| 349 | } |
| 350 | if (!open($outhandle, "|json_reformat")) { |
| 351 | print "$myname print_json: cannot pipe to json_reformat: $!\n"; |
| 352 | return; |
| 353 | } |
| 354 | while ($line = <$inhandle>) { |
| 355 | if (! ($line =~ /^##[0-9]+/)) { |
| 356 | print $outhandle $line; |
| 357 | } |
| 358 | } |
| 359 | close($outhandle); |
| 360 | close($inhandle); |
Abukar Mohamed | 8504f6a | 2019-04-03 11:07:48 +0000 | [diff] [blame] | 361 | } |
| 362 | |
Mohamed Abukar | 34e4383 | 2019-11-13 17:57:15 +0200 | [diff] [blame] | 363 | # Append an entry like ","name":"value" to the first parameter, if "name" |
| 364 | # names a variable with non-empty value. |
| 365 | # Else returns the unmodified first parameter. |
| 366 | |
| 367 | sub append_option($$) { |
| 368 | my $result = $_[0]; |
| 369 | my $var = $_[1]; |
| 370 | my $val = eval("\$$var"); |
| 371 | if ($val ne "") { |
| 372 | $result = "$result,\"$var\":\"$val\""; |
| 373 | } |
| 374 | return $result; |
| 375 | } |
| 376 | |
| 377 | # Command handlers |
Abukar Mohamed | 8504f6a | 2019-04-03 11:07:48 +0000 | [diff] [blame] | 378 | # Assumes the API currently implemented. |
Mohamed Abukar | 34e4383 | 2019-11-13 17:57:15 +0200 | [diff] [blame] | 379 | # Functions for each command below |
Abukar Mohamed | 8504f6a | 2019-04-03 11:07:48 +0000 | [diff] [blame] | 380 | |
Mohamed Abukar | 34e4383 | 2019-11-13 17:57:15 +0200 | [diff] [blame] | 381 | # Deploy: |
| 382 | # The deploy command has one mandatory parameter "name" in the API, |
| 383 | # and several optional ones. Used mainly internally for testing, because |
| 384 | # they all override Helm chart values: |
| 385 | # "helmVersion": Helm chart version to be used |
| 386 | # "releaseName": The releas name of xApp visible in K8s |
| 387 | # "namespace": Name of the namespace to which xApp is deployed. |
| 388 | # "overrideFile": The file content used to override values.yaml file |
| 389 | # this host from the host the xapp manager is running in, we use the term |
| 390 | # and variable name "podHost" here. |
| 391 | # The options come from options (see GetOptions() call). |
Abukar Mohamed | 8504f6a | 2019-04-03 11:07:48 +0000 | [diff] [blame] | 392 | |
Mohamed Abukar | 34e4383 | 2019-11-13 17:57:15 +0200 | [diff] [blame] | 393 | sub do_deploy(@) { |
| 394 | my $name = $_[0] || ""; |
| 395 | if ($name ne "") { |
| 396 | my $data = "{\"XappName\":\"$name\""; |
| 397 | $data = append_option($data, "helmVersion"); |
| 398 | $data = append_option($data, "releaseName"); |
| 399 | $data = append_option($data, "namespace"); |
| 400 | $data = append_option($data, "overrideFile"); |
| 401 | $data = $data . "}"; |
| 402 | make_temps(); |
| 403 | if (rest("POST", $base_xapps, $data)) { |
| 404 | if ($http_code eq "201") { |
| 405 | print_json $resultfile; |
| 406 | $status = 0; |
| 407 | } |
| 408 | else { |
| 409 | my $error; |
| 410 | if ($http_code eq "400") { |
| 411 | $error = "INVALID PARAMETERS SUPPLIED"; |
| 412 | } |
| 413 | elsif ($http_code eq "500") { |
| 414 | $error = "INTERNAL ERROR"; |
| 415 | } |
| 416 | else { |
| 417 | $error = "UNKNOWN STATUS $http_code"; |
| 418 | } |
| 419 | print "$error\n"; |
| 420 | $status = 1; |
| 421 | } |
| 422 | } |
| 423 | else { |
| 424 | $status=1; |
| 425 | } |
| 426 | remove_temps(); |
| 427 | } |
| 428 | else { |
| 429 | print "$myname: Error: expected the name of xapp to deploy\n"; |
| 430 | $status = 1; |
| 431 | } |
Abukar Mohamed | 8504f6a | 2019-04-03 11:07:48 +0000 | [diff] [blame] | 432 | } |
| 433 | |
Mohamed Abukar | 34e4383 | 2019-11-13 17:57:15 +0200 | [diff] [blame] | 434 | sub do_undeploy(@) { |
| 435 | my $name = $_[0] || ""; |
| 436 | my $urlpath = $base_xapps; |
| 437 | if ($name ne "") { |
| 438 | make_temps(); |
| 439 | $urlpath = "$urlpath/$name"; |
| 440 | if (rest("DELETE", $urlpath)) { |
| 441 | if ($http_code eq "204") { |
| 442 | print "SUCCESSFUL DELETION\n"; |
| 443 | $status = 0; |
| 444 | } |
| 445 | else { |
| 446 | my $error; |
| 447 | if ($http_code eq "400") { |
| 448 | $error = "INVALID XAPP NAME SUPPLIED"; |
| 449 | } |
| 450 | elsif ($http_code eq "500") { |
| 451 | $error = "INTERNAL ERROR"; |
| 452 | } |
| 453 | else { |
| 454 | $error = "UNKNOWN STATUS $http_code"; |
| 455 | } |
| 456 | print "$error\n"; |
| 457 | $status = 1; |
| 458 | } |
| 459 | } |
| 460 | else { |
| 461 | $status = 1; |
| 462 | } |
| 463 | remove_temps(); |
| 464 | } |
| 465 | else { |
| 466 | print "$myname: Error: expected the name of xapp to undeploy\n"; |
| 467 | $status = 1; |
| 468 | } |
Abukar Mohamed | 8504f6a | 2019-04-03 11:07:48 +0000 | [diff] [blame] | 469 | } |
| 470 | |
Mohamed Abukar | 34e4383 | 2019-11-13 17:57:15 +0200 | [diff] [blame] | 471 | sub do_status(@) { |
| 472 | my $name = $_[0] || ""; |
| 473 | my $instance = $_[1] || ""; |
| 474 | my $urlpath = $base_xapps; |
Abukar Mohamed | 8504f6a | 2019-04-03 11:07:48 +0000 | [diff] [blame] | 475 | |
Mohamed Abukar | 34e4383 | 2019-11-13 17:57:15 +0200 | [diff] [blame] | 476 | if ($name ne "") { |
| 477 | $urlpath = "$urlpath/$name"; |
| 478 | } |
| 479 | if ($instance ne "") { |
| 480 | $urlpath = "$urlpath/instances/$instance" |
| 481 | } |
| 482 | make_temps(); |
| 483 | if (rest("GET", $urlpath)) { |
| 484 | if ($http_code eq "200") { |
| 485 | print_json $resultfile; |
| 486 | $status = 0; |
| 487 | } |
| 488 | else { |
| 489 | my $error; |
| 490 | if ($http_code eq "400") { |
| 491 | $error = "INVALID XAPP NAME SUPPLIED"; |
| 492 | } |
| 493 | if ($http_code eq "404") { |
| 494 | $error = "XAPP NOT FOUND"; |
| 495 | } |
| 496 | elsif ($http_code eq "500") { |
| 497 | $error = "INTERNAL ERROR"; |
| 498 | } |
| 499 | else { |
| 500 | $error = "UNKNOWN STATUS $http_code"; |
| 501 | } |
| 502 | print "$error\n"; |
| 503 | $status = 1; |
| 504 | } |
| 505 | } |
| 506 | else { |
| 507 | $status = 1; |
| 508 | } |
| 509 | remove_temps(); |
Abukar Mohamed | 8504f6a | 2019-04-03 11:07:48 +0000 | [diff] [blame] | 510 | } |
| 511 | |
Mohamed Abukar | 34e4383 | 2019-11-13 17:57:15 +0200 | [diff] [blame] | 512 | # Helpers for subscription: |
Abukar Mohamed | 8504f6a | 2019-04-03 11:07:48 +0000 | [diff] [blame] | 513 | # Validate the subscription data that follows a subscription add or modify |
| 514 | # subcommand. $1=URL, $2=eventType, $3=maxRetries, $4=retryTimer |
| 515 | # URL must look like URL, event type must be one of created deleted all, |
| 516 | # maxRetries and retryTimer must be non-negative numbers. |
Mohamed Abukar | 34e4383 | 2019-11-13 17:57:15 +0200 | [diff] [blame] | 517 | # If errors, returns false (0) and prints errors, else returns 1. |
Abukar Mohamed | 8504f6a | 2019-04-03 11:07:48 +0000 | [diff] [blame] | 518 | # |
Mohamed Abukar | 34e4383 | 2019-11-13 17:57:15 +0200 | [diff] [blame] | 519 | sub validate_subscription(@) { |
| 520 | # Using the API parameter names |
| 521 | my $targetUrl = $_[0] || ""; |
| 522 | my $eventType = $_[1] || ""; |
| 523 | my $maxRetries = $_[2] || ""; |
| 524 | my $retryTimer = $_[3] || ""; |
| 525 | my $retval = 1; |
| 526 | |
| 527 | if (! ($targetUrl =~ /^http:\/\/.*/ or $targetUrl =~ /^https:\/\/.*/)) { |
| 528 | print "$myname: bad URL $targetUrl\n"; |
| 529 | $retval = 0; |
| 530 | } |
| 531 | if ($eventType ne "created" and $eventType ne "deleted" and |
| 532 | $eventType ne "all") { |
| 533 | print "$myname: unrecognized event $eventType\n"; |
| 534 | $retval = 0; |
| 535 | } |
| 536 | if (! ($maxRetries =~ /^[0-9]+$/)) { |
| 537 | print "$myname: invalid maximum retries count $maxRetries\n"; |
| 538 | $retval = 0; |
| 539 | } |
| 540 | if (! ($retryTimer =~ /^[0-9]+$/)) { |
| 541 | print "$myname: invalid retry time $retryTimer\n"; |
| 542 | $retval = 0; |
| 543 | } |
| 544 | return $retval; |
Abukar Mohamed | 8504f6a | 2019-04-03 11:07:48 +0000 | [diff] [blame] | 545 | } |
| 546 | |
Mohamed Abukar | 34e4383 | 2019-11-13 17:57:15 +0200 | [diff] [blame] | 547 | # Format a subscriptionRequest JSON object |
| 548 | |
| 549 | sub make_subscriptionRequest(@) { |
| 550 | my $targetUrl = $_[0]; |
| 551 | my $eventType = $_[1]; |
| 552 | my $maxRetries = $_[2]; |
| 553 | my $retryTimer = $_[3]; |
| 554 | return "{\"Data\": {\"TargetUrl\":\"$targetUrl\",\"EventType\":\"$eventType\",\"MaxRetries\":$maxRetries,\"RetryTimer\":$retryTimer}}"; |
Abukar Mohamed | 8504f6a | 2019-04-03 11:07:48 +0000 | [diff] [blame] | 555 | } |
| 556 | |
Mohamed Abukar | 34e4383 | 2019-11-13 17:57:15 +0200 | [diff] [blame] | 557 | # Subscriptions: |
| 558 | # $1 is sub-command: list, add, delete, modify |
| 559 | |
| 560 | sub do_subscriptions(@) { |
| 561 | my $subcommand = $_[0] || ""; |
| 562 | shift; |
| 563 | |
| 564 | my %subcommands = ( |
| 565 | "list" => \&do_subscription_list, |
| 566 | "add" => \&do_subscription_add, |
| 567 | "delete" => \&do_subscription_delete, |
| 568 | "del" => \&do_subscription_delete, |
| 569 | "modify" => \&do_subscription_modify, |
| 570 | "mod" => \&do_subscription_modify |
| 571 | ); |
| 572 | if (exists $subcommands{$subcommand}) { |
| 573 | $subcommands{$subcommand}(@_); |
| 574 | } |
| 575 | else { |
| 576 | print "$myname: unrecognized subscriptions subcommand $subcommand\n"; |
| 577 | helphint(); |
| 578 | $status=1 |
| 579 | } |
Mohamed Abukar | b175b94 | 2019-05-09 16:30:58 +0300 | [diff] [blame] | 580 | } |
| 581 | |
Mohamed Abukar | 34e4383 | 2019-11-13 17:57:15 +0200 | [diff] [blame] | 582 | # list: With empty parameter, list all, else the parameter is |
| 583 | # a subscriptionId |
Abukar Mohamed | 8504f6a | 2019-04-03 11:07:48 +0000 | [diff] [blame] | 584 | |
Mohamed Abukar | 34e4383 | 2019-11-13 17:57:15 +0200 | [diff] [blame] | 585 | sub do_subscription_list(@) { |
| 586 | my $urlpath=$base_subs; |
| 587 | my $subscriptionId = $_[0] || ""; |
| 588 | if ($subscriptionId ne "") { |
| 589 | $urlpath = "$urlpath/$subscriptionId"; |
| 590 | } |
| 591 | make_temps(); |
| 592 | if (rest("GET", $urlpath)) { |
| 593 | if ($http_code eq "200") { |
| 594 | print_json $resultfile; |
| 595 | $status = 0; |
| 596 | } |
| 597 | else { |
| 598 | my $error; |
| 599 | if ($http_code eq "400") { |
| 600 | $error = "INVALID SUBSCRIPTION ID $subscriptionId"; |
| 601 | } |
| 602 | elsif ($http_code eq "404") { |
| 603 | $error = "SUBSCRIPTION $subscriptionId NOT FOUND"; |
| 604 | } |
| 605 | elsif ($http_code eq "500") { |
| 606 | $error = "INTERNAL ERROR"; |
| 607 | } |
| 608 | else { |
| 609 | $error = "UNKNOWN STATUS $http_code"; |
| 610 | } |
| 611 | print "$error\n"; |
| 612 | $status = 1; |
| 613 | } |
| 614 | } |
| 615 | else { |
| 616 | $status=1; |
| 617 | } |
| 618 | remove_temps(); |
| 619 | } |
| 620 | |
| 621 | sub do_subscription_add(@) { |
| 622 | my $urlpath=$base_subs; |
| 623 | |
| 624 | if (validate_subscription(@_)) { |
| 625 | make_temps(); |
| 626 | if (rest("POST", $urlpath, make_subscriptionRequest(@_))) { |
| 627 | if ($http_code eq "201") { |
| 628 | print_json $resultfile; |
| 629 | $status = 0; |
| 630 | } |
| 631 | else { |
| 632 | my $error; |
| 633 | if ($http_code eq "400") { |
| 634 | $error = "INVALID INPUT"; |
| 635 | } |
| 636 | elsif ($http_code eq "500") { |
| 637 | $error = "INTERNAL ERROR"; |
| 638 | } |
| 639 | else { |
| 640 | $error = "UNKNOWN STATUS $http_code"; |
| 641 | } |
| 642 | print "$error\n"; |
| 643 | $status = 1; |
| 644 | } |
| 645 | } |
| 646 | else { |
| 647 | $status=1; |
| 648 | } |
| 649 | remove_temps(); |
| 650 | } |
| 651 | else { |
| 652 | $status = 1; |
| 653 | } |
| 654 | } |
| 655 | |
| 656 | sub do_subscription_delete(@) { |
| 657 | my $urlpath=$base_subs; |
| 658 | my $subscriptionId = $_[0] || ""; |
| 659 | if ($subscriptionId ne "") { |
| 660 | $urlpath = "$urlpath/$subscriptionId"; |
| 661 | } |
| 662 | else { |
| 663 | print "$myname: delete: Subscription id required\n"; |
| 664 | $status=1; |
| 665 | return; |
| 666 | } |
| 667 | make_temps(); |
| 668 | if (rest("DELETE", $urlpath)) { |
| 669 | if ($http_code eq "204") { |
| 670 | print "SUBSCRIPTION $subscriptionId DELETED\n"; |
| 671 | $status = 0; |
| 672 | } |
| 673 | else { |
| 674 | my $error; |
| 675 | if ($http_code eq "400") { |
| 676 | $error = "INVALID SUBSCRIPTION ID $subscriptionId"; |
| 677 | } |
| 678 | elsif ($http_code eq "500") { |
| 679 | $error = "INTERNAL ERROR"; |
| 680 | } |
| 681 | else { |
| 682 | $error = "UNKNOWN STATUS $http_code"; |
| 683 | } |
| 684 | print "$error\n"; |
| 685 | $status = 1; |
| 686 | } |
| 687 | } |
| 688 | else { |
| 689 | $status = 1; |
| 690 | } |
| 691 | remove_temps(); |
| 692 | } |
| 693 | |
| 694 | sub do_subscription_modify(@) { |
| 695 | my $urlpath=$base_subs; |
| 696 | if (defined $_[0]) { |
| 697 | $urlpath = "$urlpath/$_[0]"; |
| 698 | } |
| 699 | else { |
| 700 | print "$myname: modify: Subscription id required\n"; |
| 701 | $status=1; |
| 702 | return; |
| 703 | } |
| 704 | shift; |
| 705 | if (validate_subscription(@_)) { |
| 706 | make_temps(); |
| 707 | if (rest("PUT", $urlpath, make_subscriptionRequest(@_))) { |
| 708 | if ($http_code eq "200") { |
| 709 | print_json $resultfile; |
| 710 | $status = 0; |
| 711 | } |
| 712 | else { |
| 713 | my $error; |
| 714 | if ($http_code eq "400") { |
| 715 | $error = "INVALID INPUT"; |
| 716 | } |
| 717 | elsif ($http_code eq "500") { |
| 718 | $error = "INTERNAL ERROR"; |
| 719 | } |
| 720 | else { |
| 721 | $error = "UNKNOWN STATUS $http_code"; |
| 722 | } |
| 723 | print "$error\n"; |
| 724 | $status = 1; |
| 725 | } |
| 726 | } |
| 727 | else { |
| 728 | $status=1; |
| 729 | } |
| 730 | remove_temps(); |
| 731 | } |
| 732 | else { |
| 733 | $status = 1; |
| 734 | } |
| 735 | } |
| 736 | |
| 737 | sub do_health(@) { |
| 738 | my $urlpath=$base_health; |
| 739 | my $check = $_[0] || ""; |
| 740 | # API now defines two types of checks, either of |
| 741 | # which must be specified. |
| 742 | if ($check ne "alive" and $check ne "ready") { |
| 743 | print "$myname: health check type required (alive or ready)\n"; |
| 744 | $status=1; |
| 745 | return; |
| 746 | } |
| 747 | $urlpath = "$urlpath/$check"; |
| 748 | make_temps(); |
| 749 | if (rest("GET", $urlpath)) { |
| 750 | my $res; |
| 751 | if ($check eq "alive") { |
| 752 | # If GET succeeds at all, the xapp manager is alive, no |
| 753 | # need to check the HTTP code. |
| 754 | $res = "ALIVE"; |
| 755 | } |
| 756 | else { |
| 757 | if ($http_code eq "200") { |
| 758 | $res = "READY"; |
| 759 | } |
| 760 | elsif ($http_code eq "503") { |
| 761 | $res = "NOT READY"; |
| 762 | } |
| 763 | elsif ($http_code eq "500") { |
| 764 | $res = "INTERNAL ERROR"; |
| 765 | } |
| 766 | else { |
| 767 | $res = "UNKNOWN STATUS $http_code"; |
| 768 | } |
| 769 | } |
| 770 | print "$res\n"; |
| 771 | } |
| 772 | else { |
| 773 | $status = 1; |
| 774 | print "$myname: health check failed to contact appmgr\n"; |
| 775 | } |
| 776 | remove_temps(); |
| 777 | } |
| 778 | |
| 779 | sub do_config(@) { |
| 780 | my $subcommand = $_[0] || ""; |
| 781 | shift; |
| 782 | |
| 783 | my %subcommands = ( |
| 784 | "list" => \&do_config_list, |
| 785 | "add" => \&do_config_add, |
| 786 | "delete" => \&do_config_delete, |
| 787 | "del" => \&do_config_delete, |
| 788 | "modify" => \&do_config_modify, |
| 789 | "mod" => \&do_config_modify |
| 790 | ); |
| 791 | if (exists $subcommands{$subcommand}) { |
| 792 | $subcommands{$subcommand}(@_); |
| 793 | } |
| 794 | else { |
| 795 | print "$myname: unrecognized config subcommand $subcommand\n"; |
| 796 | helphint(); |
| 797 | $status=1 |
| 798 | } |
| 799 | } |
| 800 | |
| 801 | sub do_config_list(@) { |
| 802 | if (defined $_[0]) { |
| 803 | print "$myname: \"config list\" has no parameters\n"; |
| 804 | $status = 1; |
| 805 | return; |
| 806 | } |
| 807 | make_temps(); |
| 808 | if (rest("GET", $base_config)) { |
| 809 | if ($http_code eq "200") { |
| 810 | print_json $resultfile; |
| 811 | $status = 0; |
| 812 | } |
| 813 | else { |
| 814 | my $error; |
| 815 | if ($http_code eq "500") { |
| 816 | $error = "INTERNAL ERROR"; |
| 817 | } |
| 818 | else { |
| 819 | $error = "UNKNOWN STATUS $http_code"; |
| 820 | } |
| 821 | print "$error\n"; |
| 822 | $status = 1; |
| 823 | } |
| 824 | } |
| 825 | else { |
| 826 | $status=1; |
| 827 | } |
| 828 | remove_temps(); |
| 829 | } |
| 830 | |
| 831 | # validate_config() checks configuration commmand line. |
| 832 | # "config add" and "config modify" expect either single parameter which |
| 833 | # must be a JSON file that contains the whole thing to send (see API), |
| 834 | # or 5 parameters, where the first three are |
| 835 | # $_[0] = name |
| 836 | # $_[1] = configName (name of the configMap) |
| 837 | # $_[2] = namespace |
| 838 | # Followed by two file names: |
| 839 | # $_[3] = file containing configSchema |
| 840 | # $_[4] = file containing data for configMap |
| 841 | # Giving the last two literally on the command line does not make much sense, |
| 842 | # since they are arbitrary JSON data. |
| 843 | # On success, returns parameter count (1 or 5), depending on which kind of |
| 844 | # command line found. |
| 845 | # 0 if errors. |
| 846 | |
| 847 | # Check only the 3 names at the beginning of config add/modify/delete |
| 848 | sub validate_config_names(@) { |
| 849 | my $retval = 1; |
| 850 | # Names in the Kubernetes world consist of lowercase alphanumerics |
| 851 | # and - and . as specified in |
| 852 | # https://kubernetes.io/docs/concepts/overview/working-with-objects/name |
| 853 | for (my $idx = 0; $idx <= 2; ++$idx) { |
| 854 | if (! ($_[$idx] =~ /^[a-z][-a-z0-9.]*$/)) { |
| 855 | print "$myname: invalid characters in name $_[$idx]\n"; |
| 856 | $retval = 0; |
| 857 | } |
| 858 | } |
| 859 | return $retval; |
| 860 | } |
| 861 | |
| 862 | sub validate_config(@) { |
| 863 | my $retval = 1; |
| 864 | print "validate_config args @_\n"; |
| 865 | if ($#_ == 0) { |
| 866 | if (! -r $_[0]) { |
| 867 | print "$myname: config file $_[0] cannot be read: $!\n"; |
| 868 | $retval = 0; |
| 869 | } |
| 870 | } |
| 871 | elsif ($#_ == 4) { |
| 872 | $retval = 5; |
| 873 | if (! validate_config_names(@_)) { |
| 874 | $retval = 0; |
| 875 | } |
| 876 | for (my $idx = 3; $idx <= 4; ++$idx) { |
| 877 | if (! -r $_[$idx]) { |
| 878 | print "$myname: cannot read file $_[$idx]\n"; |
| 879 | $retval = 0; |
| 880 | } |
| 881 | } |
| 882 | } |
| 883 | else { |
| 884 | print "$myname: config add: 1 or 5 parameter expected\n"; |
| 885 | $retval = 0; |
| 886 | } |
| 887 | return $retval; |
| 888 | } |
| 889 | |
| 890 | # Generate JSON for the xAppConfig element (see API). |
| 891 | |
| 892 | sub make_xAppConfigInfo($$$) { |
| 893 | return "{\"xAppName\":\"$_[0]\",\"configMapName\":\"$_[1]\",\"namespace\":\"$_[2]\"}"; |
| 894 | } |
| 895 | |
| 896 | sub make_xAppConfig(@) { |
| 897 | my $retval = "{\"xAppConfigInfo\":" . make_xAppConfigInfo($_[0],$_[1],$_[2]); |
| 898 | my $fh; |
| 899 | open($fh, "<", $_[3]) or die "failed to open $_[3]"; |
| 900 | my @obj = <$fh>; |
| 901 | close($fh); |
| 902 | $retval = $retval . ",\"configSchema\":" . join("", @obj); |
| 903 | open($fh, "<", $_[4]) or die "failed to open $_[4]"; |
| 904 | @obj = <$fh>; |
| 905 | close($fh); |
| 906 | $retval = $retval . ",\"configMap\":" . join("", @obj) . "}"; |
| 907 | } |
| 908 | |
| 909 | sub do_config_add(@) { |
| 910 | my $paramCount; |
| 911 | |
| 912 | $paramCount = validate_config(@_); |
| 913 | if ($paramCount > 0) { |
| 914 | my $xAppConfig; |
| 915 | if ($paramCount == 1) { |
| 916 | $xAppConfig = "\@$_[0]"; |
| 917 | } |
| 918 | else { |
| 919 | $xAppConfig = make_xAppConfig(@_); |
| 920 | } |
| 921 | make_temps(); |
| 922 | if (rest("POST", $base_config, $xAppConfig)) { |
| 923 | if ($http_code eq "201") { |
| 924 | print_json $resultfile; |
| 925 | $status = 0; |
| 926 | } |
| 927 | elsif ($http_code eq "422") { # Validation failed, details in result |
| 928 | print_json $resultfile; |
| 929 | $status = 1; |
| 930 | } |
| 931 | else { |
| 932 | my $error; |
| 933 | if ($http_code eq "400") { |
| 934 | $error = "INVALID INPUT"; |
| 935 | } |
| 936 | elsif ($http_code eq "500") { |
| 937 | $error = "INTERNAL ERROR"; |
| 938 | } |
| 939 | else { |
| 940 | $error = "UNKNOWN STATUS $http_code"; |
| 941 | } |
| 942 | print "$error\n"; |
| 943 | $status = 1; |
| 944 | } |
| 945 | } |
| 946 | else { |
| 947 | $status=1; |
| 948 | } |
| 949 | remove_temps(); |
| 950 | } |
| 951 | else { |
| 952 | $status = 1; |
| 953 | } |
| 954 | } |
| 955 | |
| 956 | sub do_config_modify(@) { |
| 957 | my $paramCount; |
| 958 | |
| 959 | $paramCount = validate_config(@_); |
| 960 | if ($paramCount > 0) { |
| 961 | my $xAppConfig; |
| 962 | if ($paramCount == 1) { |
| 963 | $xAppConfig = "\@$_[0]"; |
| 964 | } |
| 965 | else { |
| 966 | $xAppConfig = make_xAppConfig(@_); |
| 967 | } |
| 968 | make_temps(); |
| 969 | if (rest("PUT", $base_config, $xAppConfig)) { |
| 970 | if ($http_code eq "200") { |
| 971 | print_json $resultfile; |
| 972 | $status = 0; |
| 973 | } |
| 974 | elsif ($http_code eq "422") { # Validation failed, details in result |
| 975 | print_json $resultfile; |
| 976 | $status = 1; |
| 977 | } |
| 978 | else { |
| 979 | my $error; |
| 980 | if ($http_code eq "400") { |
| 981 | $error = "INVALID INPUT"; |
| 982 | } |
| 983 | elsif ($http_code eq "500") { |
| 984 | $error = "INTERNAL ERROR"; |
| 985 | } |
| 986 | else { |
| 987 | $error = "UNKNOWN STATUS $http_code"; |
| 988 | } |
| 989 | print "$error\n"; |
| 990 | $status = 1; |
| 991 | } |
| 992 | } |
| 993 | else { |
| 994 | $status=1; |
| 995 | } |
| 996 | remove_temps(); |
| 997 | } |
| 998 | else { |
| 999 | $status = 1; |
| 1000 | } |
| 1001 | } |
| 1002 | |
| 1003 | # In config delete, allow either 1 parameter naming a file that contains |
| 1004 | # a JSON xAppConfigInfo object, or 3 parameters giving the |
| 1005 | # components (xAppName, configMapName, namespace), same as |
| 1006 | # in add and modify operations. |
| 1007 | |
| 1008 | sub do_config_delete(@) { |
| 1009 | my $xAppConfigInfo = ""; |
| 1010 | |
| 1011 | if ($#_ != 0 and $#_ != 2) { |
| 1012 | print "$myname: wrong number of parameters for config delete\n"; |
| 1013 | $status = 1; |
| 1014 | } |
| 1015 | elsif ($#_ == 0) { |
| 1016 | if (-r $_[0]) { |
| 1017 | $xAppConfigInfo = "\@$_[0]"; |
| 1018 | } |
| 1019 | else { |
| 1020 | print "$myname: config file $_[0] cannot be read: $!\n"; |
| 1021 | $status = 1; |
| 1022 | } |
| 1023 | } |
| 1024 | elsif (($#_ == 2) && validate_config_names(@_)) { |
| 1025 | $xAppConfigInfo = make_xAppConfigInfo($_[0],$_[1],$_[2]); |
| 1026 | } |
| 1027 | else { |
| 1028 | print "$myname: bad parameters for config delete\n"; |
| 1029 | $status = 1; |
| 1030 | } |
| 1031 | if ($xAppConfigInfo ne "") { |
| 1032 | make_temps(); |
| 1033 | if (rest("DELETE", $base_config, $xAppConfigInfo)) { |
| 1034 | if ($http_code eq "204") { |
| 1035 | print "SUCCESFUL DELETION OF CONFIG\n"; |
| 1036 | $status = 0; |
| 1037 | } |
| 1038 | else { |
| 1039 | my $error; |
| 1040 | if ($http_code eq "400") { |
| 1041 | $error = "INVALID PARAMETERS SUPPLIED"; |
| 1042 | } |
| 1043 | elsif ($http_code eq "500") { |
| 1044 | $error = "INTERNAL ERROR"; |
| 1045 | } |
| 1046 | else { |
| 1047 | $error = "UNKNOWN STATUS $http_code"; |
| 1048 | } |
| 1049 | print "$error\n"; |
| 1050 | $status = 1; |
| 1051 | } |
| 1052 | } |
| 1053 | else { |
| 1054 | $status=1; |
| 1055 | } |
| 1056 | remove_temps(); |
| 1057 | } |
| 1058 | } |