github.com/mkimuram/operator-sdk@v0.7.1-0.20190410172100-52ad33a4bda0/doc/design/milestone-0.0.2/action-api.md (about)

     1  # Operator-SDK Action API Design Doc
     2  
     3  ## Goal
     4  
     5  Define an API for performing Actions(Create,Update,Delete) that is flexible enough to allow the SDK user to execute a sequence of dependent Actions and perform error handling.
     6  
     7  ## Background
     8  
     9  For milestone `0.0.1` the SDK invokes the user provided handler for an Event, which would return a list of Actions that the SDK would execute. The motivation for this was to ensure that all Actions are taken through the SDK.
    10  
    11  ```Go
    12  // Handle reacts to events and outputs actions.
    13  // If any intended action failed, the event would be re-triggered.
    14  // For actions done before the failed action, there is no rollback.
    15  func Handle(ctx context.Context, event sdkTypes.Event) []sdkTypes.Action
    16  ```
    17  
    18  The provided actions were:
    19  - `kube-apply`: Create or Update or specified object
    20  - `kube-delete`: Delete the specified object
    21  
    22  This workflow of batch executing actions outside of the handler has the following issues:
    23  It makes it harder for the user to write their operator logic as a sequence of dependent actions and queries, e.g:
    24  - Create a ConfigMap
    25  - If it already exists
    26    - Query some application state and verify the ConfigMap data
    27    - Update the ConfigMap data with the latest state if needed
    28  
    29  The user cannot handle errors for failed actions e.g updating the status if some action fails. Currently the Handler would just be retriggered with the Event if an Action fails
    30  
    31  ## Proposed Solution
    32  
    33  The SDK should provide an API to Create, Update and Delete objects from inside the Handler. This will allow users to write the core operator logic in a more intuitive way by using a sequence of actions and queries.
    34  
    35  This method also aligns with the original goal of ensuring that all actions of the operator are taken through the SDK.
    36  
    37  ## API
    38  **Note:** `sdkTypes.Object` is just the kubernetes `runtime.Object` 
    39  
    40  ### Handler:
    41  
    42  ```Go
    43  // Handle contains the business logic for an handling an Event
    44  // It uses SDK Actions and Queries to reconcile the state
    45  // If an error is returned the Event would be requeued and sent to the Handler again
    46  func Handle(ctx context.Context, event sdkTypes.Event) error
    47  ```
    48  
    49  ### Create Update Delete:
    50  ```Go
    51  // Create creates the provided object on the server, and updates 
    52  // the local object with the generated result from the server(UID, resourceVersion, etc).
    53  // Returns an error if the object’s TypeMeta(Kind, APIVersion) or ObjectMeta(Name, Namespace) is missing or incorrect.
    54  // Can also return an api error from the server
    55  // e.g AlreadyExists https://github.com/kubernetes/apimachinery/blob/master/pkg/api/errors/errors.go#L423 
    56  func Create(object sdkTypes.Object) error
    57  ```
    58  
    59  ```Go
    60  // Update updates the provided object on the server, and updates
    61  // the local object with the generated result from the server(UID, resourceVersion, etc).
    62  // Returns an error if the object’s TypeMeta(Kind, APIVersion) or ObjectMeta(Name, Namespace) is missing or incorrect.
    63  // Can also return an api error from the server
    64  // e.g Conflict https://github.com/kubernetes/apimachinery/blob/master/pkg/api/errors/errors.go#L428 
    65  func Update(object sdkTypes.Object) error
    66  ```
    67  
    68  ```Go
    69  // Delete deletes the specified object.
    70  // Returns an error if the object’s TypeMeta(Kind, APIVersion) or ObjectMeta(Name, Namespace) is missing or incorrect.
    71  // Can also return an api error from the server
    72  // e.g NotFound https://github.com/kubernetes/apimachinery/blob/master/pkg/api/errors/errors.go#L418
    73  // “opts” configures the k8s.io/apimachinery/pkg/apis/meta/v1.DeleteOptions
    74  func Delete(object sdkTypes.Object, opts ...DeleteOption) error
    75  ```
    76  
    77  ### Example Usage:
    78  
    79  ```Go
    80  import (
    81      "k8s.io/api/core/v1"
    82      metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    83      apierrors "k8s.io/apimachinery/pkg/api/errors"
    84  )
    85  
    86  func Handle(ctx context.Context, event sdkType.Event) {
    87      ...
    88      pod := &v1.Pod{
    89          TypeMeta: metav1.TypeMeta{
    90              Kind:       "Pod",
    91              APIVersion: "v1",
    92          },
    93          ObjectMeta: metav1.ObjectMeta {
    94              Name:      "example",
    95              Namespace: "default",
    96          },
    97          Spec: v1.PodSpec{
    98              ...
    99          }
   100      }
   101  
   102      // Create
   103      err := sdk.Create(pod)
   104      if err != nil && !apierrors.IsAlreadyExists(err) {
   105          return errors.New("failed to create pod")
   106      }
   107  
   108      // Update
   109      err := sdk.Update(pod)
   110      if err != nil {
   111          return errors.New("failed to update pod")
   112      }
   113  
   114      ...
   115  	
   116      // Delete with default options
   117      err := sdk.Delete(pod)
   118      if err != nil {
   119          return errors.New("failed to delete pod")
   120      }
   121      
   122      // Delete with custom options
   123      gracePeriodSeconds := int64(5)
   124      metav1DeleteOptions := &metav1.DeleteOptions{GracePeriodSeconds: &gracePeriodSeconds}
   125      err := sdk.Delete(pod, sdk.WithDeleteOptions(metav1DeleteOptions))
   126  }
   127  ```
   128  
   129  ## Reference:
   130  
   131  ### DeleteOptions:
   132  
   133  ```Go
   134  // DeleteOp wraps all the options for Delete.
   135  type DeleteOp struct {
   136      metaDeleteOptions metav1.DeleteOptions
   137  }
   138  
   139  // DeleteOption configures DeleteOp
   140  type DeleteOption func(*DeleteOp) 
   141  
   142  // WithDeleteOptions sets the meta_v1.DeleteOptions for
   143  // the Delete() operation.
   144  func WithDeleteOptions(metaDeleteOptions *metav1.DeleteOptions) DeleteOption {
   145      return func(op *DeleteOp) {
   146          op.metaDeleteOptions = metaDeleteOptions
   147      }
   148  }
   149  ```
   150  
   151