github.com/fluxcd/go-git-providers@v0.19.3/gitprovider/gitprovider.go (about)

     1  /*
     2  Copyright 2020 The Flux CD contributors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package gitprovider
    18  
    19  import "context"
    20  
    21  // ProviderID is a typed string for a given Git provider
    22  // The provider constants are defined in their respective packages.
    23  type ProviderID string
    24  
    25  // InfoRequest is an interface which all {Object}Info objects that can be used as Create() or Reconcile()
    26  // requests in the Client should implement. Most likely, the struct should also implement DefaultedInfoRequest,
    27  // as most objects have optional, defaulted fields.
    28  type InfoRequest interface {
    29  	// ValidateInfo validates the object at {Object}.Set() and POST-time, before defaulting.
    30  	// Set (non-nil) and required fields should be validated.
    31  	ValidateInfo() error
    32  
    33  	// Equals can be used to check if this *Info request (the desired state) matches the actual
    34  	// passed in as the argument.
    35  	Equals(actual InfoRequest) bool
    36  }
    37  
    38  // DefaultedInfoRequest is a superset of InfoRequest, also including a Default() function that can
    39  // modify the underlying object, adding default values. ValidateAndDefaultInfo() can be used
    40  // to first validate, and then default.
    41  type DefaultedInfoRequest interface {
    42  	// DefaultedInfoRequest is a superset of InfoRequest
    43  	InfoRequest
    44  
    45  	// Default will be run after validation, setting optional pointer fields to their
    46  	// default values before doing the POST request. This function MUST be registered with
    47  	// the base struct as a pointer receiver.
    48  	Default()
    49  }
    50  
    51  // Updatable is an interface which all objects that can be updated
    52  // using the Client implement.
    53  type Updatable interface {
    54  	// Update will apply the desired state in this object to the server.
    55  	// Only set fields will be respected (i.e. PATCH behaviour).
    56  	// In order to apply changes to this object, use the .Set({Resource}Info) error
    57  	// function, or cast .APIObject() to a pointer to the provider-specific type
    58  	// and set custom fields there.
    59  	//
    60  	// ErrNotFound is returned if the resource does not exist.
    61  	//
    62  	// The internal API object will be overridden with the received server data.
    63  	Update(ctx context.Context) error
    64  }
    65  
    66  // Deletable is an interface which all objects that can be deleted
    67  // using the Client implement.
    68  type Deletable interface {
    69  	// Delete deletes the current resource irreversibly.
    70  	//
    71  	// ErrNotFound is returned if the resource doesn't exist anymore.
    72  	Delete(ctx context.Context) error
    73  }
    74  
    75  // Reconcilable is an interface which all objects that can be reconciled
    76  // using the Client implement.
    77  type Reconcilable interface {
    78  	// Reconcile makes sure the desired state in this object (called "req" here) becomes
    79  	// the actual state in the backing Git provider.
    80  	//
    81  	// If req doesn't exist under the hood, it is created (actionTaken == true).
    82  	// If req doesn't equal the actual state, the resource will be updated (actionTaken == true).
    83  	// If req is already the actual state, this is a no-op (actionTaken == false).
    84  	//
    85  	// The internal API object will be overridden with the received server data if actionTaken == true.
    86  	Reconcile(ctx context.Context) (actionTaken bool, err error)
    87  }
    88  
    89  // Object is the interface all types should implement.
    90  type Object interface {
    91  	// APIObject returns the underlying value that was returned from the server.
    92  	// This is always a pointer to a struct.
    93  	APIObject() interface{}
    94  }
    95  
    96  // OrganizationBound describes an object that is bound to a given organization, e.g. a team.
    97  type OrganizationBound interface {
    98  	// Organization returns the OrganizationRef associated with this object.
    99  	Organization() OrganizationRef
   100  }
   101  
   102  // RepositoryBound describes an object that is bound to a given repository, e.g. a deploy key.
   103  type RepositoryBound interface {
   104  	// Repository returns the RepositoryRef associated with this object.
   105  	Repository() RepositoryRef
   106  }
   107  
   108  // ValidateAndDefaultInfo can be used in client Create() and Reconcile() functions, where the
   109  // request object, which implements InfoRequest, shall be first validated, and then defaulted.
   110  // Defaulting happens at Create(), because we want to consistently apply this library's defaults
   111  // across providers. Defaulting also happens at Reconcile(), because as the object has been created
   112  // with defaults, the actual state fetched from the server will contain those defaults, and would
   113  // result in a diff between the (possibly non-defaulted) request and actual state.
   114  // TODO: Unit and integration test this.
   115  // TODO: Document in Create() and Reconcile() that req is modified (?) and should not be used anymore.
   116  func ValidateAndDefaultInfo(info DefaultedInfoRequest) error {
   117  	if err := info.ValidateInfo(); err != nil {
   118  		return err
   119  	}
   120  	info.Default()
   121  	return nil
   122  }