1:- module(kubepl, [
    2                   initialize/4,        % +URI, +AuthOptions, +HTTPOptions, -Client
    3                   initialize/5,        % +URI, +Version, +AuthOptions, +HTTPOptions, -Client
    4                   get_resources/2,     % +Client, -Response
    5                   get/5,               % +Client, +Entity, +EntityConfig, +Params, -Responsew
    6                   get/6,               % +Client, +Entity, +EntityConfig, +Params, +Body, -Response
    7                   delete/5,            % +Client, +Entity, +EntityConfig, +Params, -Response
    8                   delete/6,            % +Client, +Entity, +EntityConfig, +Params, +Body, -Response
    9                   create/5,            % +Client, +Entity, +EntityConfig, +Params, -Response
   10                   create/6,            % +Client, +Entity, +EntityConfig, +Params, +Body, -Response
   11                   update/5,            % +Client, +Entity, +EntityConfig, +Params, -Response
   12                   update/6,            % +Client, +Entity, +EntityConfig, +Params, +Body, -Response
   13                   partially_update/7,  % +Client, +Entity, +EntityConfig, +Params, +Body, +PatchType, -Response
   14                   proxy_get/5,         % +Client, +Entity, +EntityConfig, +Params, -Response
   15                   proxy_get/6,         % +Client, +Entity, +EntityConfig, +Params, +Body, -Response
   16                   proxy_delete/5,      % +Client, +Entity, +EntityConfig, +Params, -Responsew
   17                   proxy_delete/6,      % +Client, +Entity, +EntityConfig, +Params, +Body, -Response
   18                   proxy_post/5,        % +Client, +Entity, +EntityConfig, +Params, -Responsew
   19                   proxy_post/6,        % +Client, +Entity, +EntityConfig, +Params, +Body, -Response
   20                   proxy_put/5,         % +Client, +Entity, +EntityConfig, +Params, -Responsew
   21                   proxy_put/6,         % +Client, +Entity, +EntityConfig, +Params, +Body, -Response
   22                   proxy_head/5,        % +Client, +Entity, +EntityConfig, +Params, -Responsew
   23                   proxy_options/5      % +Client, +Entity, +EntityConfig, +Params, -Responsew
   24                  ]).

Kubernetes Client

Check http://kubernetes.io API Reference document for details.

author
- Hongxin Liang
license
- Apache License Version 2.0 */
   33:- use_module(library(http/http_client)).   34:- use_module(library(http/http_ssl_plugin)).   35:- use_module(library(http/http_json)).   36:- use_module(library(http/json)).   37:- use_module(library(ssl)).
 initialize(+URI, +AuthOptions, +HTTPOptions, -Client) is semidet
 initialize(+URI, +Version, +AuthOptions, +HTTPOptions, -Client) is semidet
Initialize the client.
   54initialize(URI, AuthOptions, HTTPOptions, Client) :-
   55    merge_options(AuthOptions, HTTPOptions, Options),
   56    Client = kubeplc(_{
   57                       uri:URI,
   58                       options:Options
   59                      }).
   60
   61initialize(URI, Version, AuthOptions, HTTPOptions, Client) :-
   62    merge_options(AuthOptions, HTTPOptions, Options),
   63    Client = kubeplc(_{
   64                       uri:URI,
   65                       version:Version,
   66                       options:Options
   67                      }).
 get_resources(+Client, -Response)
Get available resources.
   73get_resources(Client, Response) :-
   74    get(Client, '', _{}, [], _, Response).
Get entities, for example =namespace, pods, services=, etc.

For entity who needs additional configuration, use EntityConfig, for example _{namespace:Namespace, name:Name, suffix:Suffix}; otherwise pass an empty dictionary. Suffix can be arbitrary atom including a slash-separated context for example some/context.

For all valid query parameters, please refer to Kubernetes API Reference document.

Body must be a valid dictionary according to the entity spec.

HTTP status code will be ignored becaise Kubernetes encodes whatever message in Response.

   93get(Client, Entity, EntityConfig, Params, Response) :-
   94    get(Client, Entity, EntityConfig, Params, _, Response).
   95
   96get(kubeplc(Config), Entity, EntityConfig, Params, Body, Response) :-
   97    build_url(Config, Entity, EntityConfig, Params, URL),
   98    (   var(Body)
   99    ->  http_get(URL, Response, [status_code(_),json_object(dict)|Config.options])
  100    ;   http_post(URL, json(Body), Response,
  101                  [method(get),status_code(_),json_object(dict)|Config.options])
  102    ).
Delete entities, for example =namespace, pods, services=, etc.

For entity who needs additional configuration, use EntityConfig, for example _{namespace:Namespace, name:Name, suffix:Suffix}; otherwise pass an empty dictionary. Suffix can be arbitrary atom including a slash-separated context for example some/context.

For all valid query parameters, please refer to Kubernetes API Reference document.

Body must be a valid dictionary according to the entity spec.

HTTP status code will be ignored becaise Kubernetes encodes whatever message in Response.

  121delete(Client, Entity, EntityConfig, Params, Response) :-
  122    delete(Client, Entity, EntityConfig, Params, _, Response).
  123
  124delete(kubeplc(Config), Entity, EntityConfig, Params, Body, Response) :-
  125    build_url(Config, Entity, EntityConfig, Params, URL),
  126    (   var(Body)
  127    ->  http_delete(URL, Response, [status_code(_),json_object(dict)|Config.options])
  128    ;   http_post(URL, json(Body), Response,
  129                  [method(delete),status_code(_),json_object(dict)|Config.options])
  130    ).
Create entities, for example =namespace, pods, services=, etc.

For entity who needs additional configuration, use EntityConfig, for example _{namespace:Namespace, name:Name, suffix:Suffix}; otherwise pass an empty dictionary. Suffix can be arbitrary atom including a slash-separated context for example some/context.

For all valid query parameters, please refer to Kubernetes API Reference document.

Body must be a valid dictionary according to the entity spec.

HTTP status code will be ignored becaise Kubernetes encodes whatever message in Response.

  149create(Client, Entity, EntityConfig, Params, Response) :-
  150    create(Client, Entity, EntityConfig, Params, _, Response).
  151
  152create(kubeplc(Config), Entity, EntityConfig, Params, Body, Response) :-
  153    build_url(Config, Entity, EntityConfig, Params, URL),
  154    (   var(Body)
  155    ->  http_post(URL, code(''), Response, [status_code(_),json_object(dict)|Config.options])
  156    ;   http_post(URL, json(Body), Response,
  157                 [status_code(_),json_object(dict)|Config.options])
  158    ).
Update entities, for example =namespace, pods, services=, etc.

For entity who needs additional configuration, use EntityConfig, for example _{namespace:Namespace, name:Name, suffix:Suffix}; otherwise pass an empty dictionary. Suffix can be arbitrary atom including a slash-separated context for example some/context.

For all valid query parameters, please refer to Kubernetes API Reference document.

Body must be a valid dictionary according to the entity spec.

HTTP status code will be ignored becaise Kubernetes encodes whatever message in Response.

  177update(Client, Entity, EntityConfig, Params, Response) :-
  178    update(Client, Entity, EntityConfig, Params, _, Response).
  179
  180update(kubeplc(Config), Entity, EntityConfig, Params, Body, Response) :-
  181    build_url(Config, Entity, EntityConfig, Params, URL),
  182    (   var(Body)
  183    ->  http_put(URL, code(''), Response, [status_code(_),json_object(dict)|Config.options])
  184    ;   http_put(URL, json(Body), Response,
  185                 [status_code(_),json_object(dict)|Config.options])
  186    ).
 partially_update(+Client, +Entity, +EntityConfig, +Params, +Body, +PatchType, -Response)
Partially update entities, for example =event, limit_range=, etc.

For entity who needs additional configuration, use EntityConfig, for example _{namespace:Namespace, name:Name, suffix:Suffix}; otherwise pass an empty dictionary. Suffix can be arbitrary atom including a slash-separated context for example some/context.

For all valid query parameters, please refer to Kubernetes API Reference document.

Body must be a valid dictionary according to the entity spec.

Valid PatchType is one of json, merge, or strategic-merge.

HTTP status code will be ignored becaise Kubernetes encodes whatever message in Response.

  206partially_update(kubeplc(Config), Entity, EntityConfig, Params, Body, PatchType, Response) :-
  207    build_url(Config, Entity, EntityConfig, Params, URL),
  208    atom_json_term(Codes, Body, [as(codes)]),
  209    atomic_list_concat(['application/',PatchType,'-patch','+json'], ContentType),
  210    http_patch(URL, bytes(ContentType, Codes), Response,
  211               [status_code(_),json_object(dict)|Config.options]).
Proxy GET request towards entities, for example =namespace, pods, services=, etc.

For entity who needs additional configuration, use EntityConfig, for example _{namespace:Namespace, name:Name}; otherwise pass an empty dictionary.

For all valid query parameters, please refer to Kubernetes API Reference document.

Body must be a valid dictionary according to the entity spec.

HTTP status code will be ignored becaise Kubernetes encodes whatever message in Response.

  228proxy_get(Client, Entity, EntityConfig, Params, Response) :-
  229    proxy_get(Client, Entity, EntityConfig, Params, _, Response).
  230
  231proxy_get(Client, Entity, EntityConfig, Params, Body, Response) :-
  232    get(Client, Entity, EntityConfig.put(suffix, proxy), Params, Body, Response).
Proxy DELETE request towards entities, for example =namespace, pods, services=, etc.

For entity who needs additional configuration, use EntityConfig, for example _{namespace:Namespace, name:Name}; otherwise pass an empty dictionary.

For all valid query parameters, please refer to Kubernetes API Reference document.

Body must be a valid dictionary according to the entity spec.

HTTP status code will be ignored becaise Kubernetes encodes whatever message in Response.

  249proxy_delete(Client, Entity, EntityConfig, Params, Response) :-
  250    proxy_delete(Client, Entity, EntityConfig, Params, _, Response).
  251
  252proxy_delete(Client, Entity, EntityConfig, Params, Body, Response) :-
  253    delete(Client, Entity, EntityConfig.put(suffix, proxy), Params, Body, Response).
Proxy POST request towards entities, for example =namespace, pods, services=, etc.

For entity who needs additional configuration, use EntityConfig, for example _{namespace:Namespace, name:Name}; otherwise pass an empty dictionary.

For all valid query parameters, please refer to Kubernetes API Reference document.

Body must be a valid dictionary according to the entity spec.

HTTP status code will be ignored becaise Kubernetes encodes whatever message in Response.

  270proxy_post(Client, Entity, EntityConfig, Params, Response) :-
  271    proxy_post(Client, Entity, EntityConfig, Params, _, Response).
  272
  273proxy_post(Client, Entity, EntityConfig, Params, Body, Response) :-
  274    create(Client, Entity, EntityConfig.put(suffix, proxy), Params, Body, Response).
Proxy PUT request towards entities, for example =namespace, pods, services=, etc.

For entity who needs additional configuration, use EntityConfig, for example _{namespace:Namespace, name:Name}; otherwise pass an empty dictionary.

For all valid query parameters, please refer to Kubernetes API Reference document.

Body must be a valid dictionary according to the entity spec.

HTTP status code will be ignored becaise Kubernetes encodes whatever message in Response.

  291proxy_put(Client, Entity, EntityConfig, Params, Response) :-
  292    proxy_put(Client, Entity, EntityConfig, Params, _, Response).
  293
  294proxy_put(Client, Entity, EntityConfig, Params, Body, Response) :-
  295    update(Client, Entity, EntityConfig.put(suffix, proxy), Params, Body, Response).
 proxy_head(+Client, +Entity, +EntityConfig, +Params, -Response)
Proxy HEAD request towards entities, for example =namespace, pods, services=, etc.

For entity who needs additional configuration, use EntityConfig, for example _{namespace:Namespace, name:Name, suffix:Suffix}; otherwise pass an empty dictionary. Suffix can be arbitrary atom including a slash-separated context for example some/context.

For all valid query parameters, please refer to Kubernetes API Reference document.

Body must be a valid dictionary according to the entity spec.

HTTP status code will be ignored becaise Kubernetes encodes whatever message in Response.

  313proxy_head(kubeplc(Config), Entity, EntityConfig, Params, Response) :-
  314    build_url(Config, Entity, EntityConfig.put(suffix, proxy), Params, URL),
  315    http_get(URL, Response, [method(head),status_code(_),json_object(dict)|Config.options]).
 proxy_options(+Client, +Entity, +EntityConfig, +Params, -Response)
Proxy OPTIONS request towards entities, for example =namespace, pods, services=, etc.

For entity who needs additional configuration, use EntityConfig, for example _{namespace:Namespace, name:Name, suffix:Suffix}; otherwise pass an empty dictionary. Suffix can be arbitrary atom including a slash-separated context for example some/context.

For all valid query parameters, please refer to Kubernetes API Reference document.

Body must be a valid dictionary according to the entity spec.

HTTP status code will be ignored becaise Kubernetes encodes whatever message in Response.

  333proxy_options(kubeplc(Config), Entity, EntityConfig, Params, Response) :-
  334    build_url(Config, Entity, EntityConfig.put(suffix, proxy), Params, URL),
  335    http_get(URL, Response, [method(options),status_code(_),json_object(dict)|Config.options]).
  336
  337merge_options(auth(basic_auth, Options), HTTPOptions, MergedOptions) :- !,
  338    memberck(user(User), Options),
  339    memberck(password(Password), Options),
  340    MergedOptions = [authorization(basic(User, Password))|HTTPOptions].
  341
  342merge_options(auth(bearer_token, Options), HTTPOptions, MergedOptions) :- !,
  343    [token(BearerToken)] = Options,
  344    atom_concat('Bearer ', BearerToken, Value),
  345    MergedOptions = [request_header('Authorization'=Value)|HTTPOptions].
  346
  347merge_options(auth(ssl, Options), HTTPOptions, MergedOptions) :- !,
  348    append(HTTPOptions, Options, MergedOptions).
  349
  350merge_options(auth(none), HTTPOptions, HTTPOptions).
  351
  352build_url(Config, Entity, EntityConfig, Params, URL) :-
  353    add_version(Config, URL0),
  354    add_namespace(URL0, EntityConfig, URL1),
  355    atomic_list_concat([URL1,Entity], '/', URL2),
  356    add_entity_property(URL2, EntityConfig, name, URL3),
  357    add_entity_property(URL3, EntityConfig, suffix, URL4),
  358    (   Params \= []
  359    ->  uri_query_components(Query, Params),
  360        atomic_list_concat([URL4,'?',Query], URL)
  361    ;   URL = URL4
  362    ),
  363    debug(kubepl, 'URL ~w', [URL]).
  364
  365add_version(Config, URL) :-
  366    (   Version = Config.get(version)
  367    ->  atomic_list_concat([Config.uri,Version], '/', URL)
  368    ;   URL = Config.uri
  369    ).
  370
  371add_namespace(URL0, EntityConfig, URL) :-
  372    (   Namespace = EntityConfig.get(namespace)
  373    ->  atomic_list_concat([URL0,namespaces,Namespace], '/', URL)
  374    ;   URL = URL0
  375    ).
  376
  377add_entity_property(URL0, EntityConfig, PropertyName, URL) :-
  378    (   Property = EntityConfig.get(PropertyName)
  379    ->  atomic_list_concat([URL0,Property], '/', URL)
  380    ;   URL = URL0
  381    )