coryodaniel/k8s

Dialyzer errors with K8s.Client functions

linkdd opened this issue · 3 comments

K8s.Client.watch/3

3rd argument expects keyword(atom()) but not every options are an atom.

The function call will not succeed.

K8s.Client.watch(
  any(),
  _operation :: %K8s.Operation{
    :api_version => binary(),
    :data => nil | map(),
    :method => atom(),
    :name => atom() | binary() | {binary(), binary()},
    :path_params => Keyword.t(atom()),
    :query_params => [],
    :verb => atom()
  },
  [{:stream_to, pid()}, ...]
)

will never return since the 3rd arguments differ
from the success typing arguments:

(
  %K8s.Conn{
    :auth => nil | struct(),
    :ca_cert => nil | binary(),
    :cluster_name => nil | binary(),
    :discovery_driver => atom(),
    :discovery_opts => Keyword.t(),
    :http_provider => atom(),
    :insecure_skip_tls_verify => boolean(),
    :middleware => %K8s.Middleware.Stack{:request => [atom()], :response => [atom()]},
    :url => binary(),
    :user_name => nil | binary()
  },
  %K8s.Operation{
    :api_version => binary(),
    :data => nil | map(),
    :method => atom(),
    :name => atom() | binary() | {binary(), binary()},
    :path_params => Keyword.t(atom()),
    :query_params => Keyword.t(),
    :verb => atom()
  },
  Keyword.t(atom())
)

K8s.Client.wait_until/3

3rd argument expects keyword(atom()) but not every options are an atom.

The function call will not succeed.

K8s.Client.wait_until(
  _conn :: %K8s.Conn{
    :auth => nil | struct(),
    :ca_cert => nil | binary(),
    :cluster_name => nil | binary(),
    :discovery_driver => atom(),
    :discovery_opts => [{_, _}],
    :http_provider => atom(),
    :insecure_skip_tls_verify => boolean(),
    :middleware => %K8s.Middleware.Stack{:request => [any()], :response => [any()]},
    :url => binary(),
    :user_name => nil | binary()
  },
  _operation :: %K8s.Operation{
    :api_version => binary(),
    :data => nil | map(),
    :method => atom(),
    :name => atom() | binary() | {binary(), binary()},
    :path_params => Keyword.t(atom()),
    :query_params => [],
    :verb => atom()
  },
  _wait_opts :: [
    {:eval, (_ -> boolean())} | {:find, [<<_::48, _::size(64)>>, ...]} | {:timeout, 60},
    ...
  ]
)

will never return since the 3rd arguments differ
from the success typing arguments:

(
  %K8s.Conn{
    :auth => nil | struct(),
    :ca_cert => nil | binary(),
    :cluster_name => nil | binary(),
    :discovery_driver => atom(),
    :discovery_opts => Keyword.t(),
    :http_provider => atom(),
    :insecure_skip_tls_verify => boolean(),
    :middleware => %K8s.Middleware.Stack{:request => [atom()], :response => [atom()]},
    :url => binary(),
    :user_name => nil | binary()
  },
  %K8s.Operation{
    :api_version => binary(),
    :data => nil | map(),
    :method => atom(),
    :name => atom() | binary() | {binary(), binary()},
    :path_params => Keyword.t(atom()),
    :query_params => Keyword.t(),
    :verb => atom()
  },
  Keyword.t(atom())
)

Would changing this to Keyword.t(any()) be appropriate? Happy to put in a PR.

Having written my fair share of TypeScript and some Rust, using any seems like a red-flag for me.

I would do something like:

@type api_version_opt :: {:api_version, binary()}
@type http_provider_opt :: {:http_provider, atom()}
@type insecure_skip_tls_verify_opt :: {:insecure_skip_tls_verify, boolean()}
# ...

@type opt :: api_version_opt | http_provider_opt | insecure_skip_tls_verify_opt # | ...
@type opts :: list(opt)

In order to fix the issue at hand, I would go for keyword().

Typespecs could be optimised as proposed by @linkdd. I don't see it being straight forward in this case as the opts are forwarded to other modules which makes them hard to define. So in order to get the issue fixed sooner rather than later, I would "outscope" typespec optimisation.