# `Bonny.ControllerV2`
[🔗](https://github.com/coryodaniel/bonny/blob/v1.5.0/lib/bonny/controller_v2.ex#L1)

Controllers handle action events observed by a resource watch query.
Controllers must be registered at the operator together with the resource
watch query. The operator will then delegate events observed by that query for
processing to this controller

Controllers use the `Pluggable.StepBuilder` to build a step in the processing
pipeline. In order to use it, a step has to be defined and implemented in the
controller. The step must have the following spec

    step_name(Bonny.Axn.t(), keyword()) :: Bonny.Axn.t()

The modules `Bonny.Axn` module is imported to your controller. In your event
handler step you should use the functions `Bonny.Axn.register_descendant/3`,
`Bonny.Axn.update_status/2` and the ones to  register events:
`Bonny.Axn.success_event/2`, `Bonny.Axn.failure_event/2` and/or
`Bonny.Axn.register_event/6`. Note that these functions raise
exceptions if those resources have already been applied to the cluster.

## Example

Match against the struct's `:action` field which is one of `:add`, `:modify`,
`:reconcile` or `:delete` to provide an implementation for each case.

    defmodule MyOperator.Controller.CronTabController do

      # other steps
      step :handle_event
      # other steps

      # apply the resource
      def handle_event(%Bonny.Axn{action: action, resource: resource} = axn, _opts)
          when action in [:add, :modify, :reconcile] do
        success_event(axn)
      end

      def handle_event(%Bonny.Axn{action: :delete, resource: resource} = axn, _opts) do
        #
        axn
      end
    end

Registering your descendants with the `%Bonny.Axn{}` token makes your
controller easier to test. Be sure to add `Bonny.Pluggable.ApplyDescendants`
as step to your operator in order for the descendants to be applied to the
cluster.

    defmodule MyOperator.Controller.CronTabController do

      # other steps
      step :handle_event
      # other steps

      # apply the resource
      def handle_event(axn, _opts) do
        deployment = generate_deployment(axn.resource)

        axn
        |> register_descendant(deployment)
        |> success_event()
      end
    end

Use `Bonny.Axn.update_status/2` to store API responses or other status data in the
resource status. Be sure to enable the status subresource in your CRD version
module.

    defmodule MyOperator.Controller.CronTabController do

      # other steps
      step :handle_event
      # other steps

      # apply the resource
      def handle_event(axn, _opts) do
        response = apply_state(axn.resource)

        axn
        |> update_status(fn status ->
          Map.put(status, "response", response)
        end)
        |> success_event()
      end
    end

# `api`

```elixir
@type api() :: binary()
```

# `rbac_rule`

```elixir
@type rbac_rule() :: %{apiGroups: [api()], resources: [resource()], verbs: [verb()]}
```

# `resource`

```elixir
@type resource() :: binary()
```

# `verb`

```elixir
@type verb() :: binary()
```

# `rbac_rules`

```elixir
@callback rbac_rules() :: [rbac_rule()]
```

# `child_spec`

Returns a specification to start this module under a supervisor.

See `Supervisor`.

# `start_link`

# `to_rbac_rule`

```elixir
@spec to_rbac_rule({api() | [api()], resource() | [resource()], verb() | [verb()]}) ::
  rbac_rule()
```

---

*Consult [api-reference.md](api-reference.md) for complete listing*
