github.com/wmuizelaar/kpt@v0.0.0-20221018115725-bd564717b2ed/internal/errors/resolver/live.go (about)

     1  // Copyright 2021 Google LLC
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package resolver
    16  
    17  import (
    18  	initialization "github.com/GoogleContainerTools/kpt/commands/live/init"
    19  	"github.com/GoogleContainerTools/kpt/internal/cmdutil"
    20  	"github.com/GoogleContainerTools/kpt/internal/errors"
    21  	"github.com/GoogleContainerTools/kpt/internal/pkg"
    22  	"github.com/GoogleContainerTools/kpt/pkg/live"
    23  	"sigs.k8s.io/cli-utils/pkg/inventory"
    24  	"sigs.k8s.io/cli-utils/pkg/manifestreader"
    25  	"sigs.k8s.io/cli-utils/pkg/print/common"
    26  )
    27  
    28  //nolint:gochecknoinits
    29  func init() {
    30  	AddErrorResolver(&liveErrorResolver{})
    31  }
    32  
    33  const (
    34  	noInventoryObjErrorMsg = `
    35  Error: Package uninitialized. Please run "kpt live init" command.
    36  
    37  The package needs to be initialized to generate the template
    38  which will store state for resource sets. This state is
    39  necessary to perform functionality such as deleting an entire
    40  package or automatically deleting omitted resources (pruning).
    41  `
    42  	multipleInventoryObjErrorMsg = `
    43  Error: Package has multiple inventory object templates.
    44  
    45  The package should have one and only one inventory object template.
    46  `
    47  
    48  	resourceGroupCRDInstallErrorMsg = `
    49  Error: Unable to install the ResourceGroup CRD.
    50  
    51  {{- if gt (len .cause) 0 }}
    52  {{ printf "\nDetails:" }}
    53  {{ printf "%s" .cause }}
    54  {{- end }}
    55  `
    56  	//nolint:lll
    57  	noResourceGroupCRDMsg = `
    58  Error: The ResourceGroup CRD was not found in the cluster. Please install it either by using the '--install-resource-group' flag or the 'kpt live install-resource-group' command.
    59  `
    60  
    61  	//nolint:lll
    62  	invInfoAlreadyExistsMsg = `
    63  Error: Inventory information has already been added to the package. Changing it after a package has been applied to the cluster can lead to undesired results. Use the --force flag to suppress this error.
    64  `
    65  
    66  	//nolint:lll
    67  	invInfoInRGAlreadyExistsMsg = `
    68  Error: Inventory information has already been added to the package ResourceGroup object. Changing it after a package has been applied to the cluster can lead to undesired results. Use the --force flag to suppress this error.
    69  `
    70  
    71  	//nolint:lll
    72  	invInfoInKfAlreadyExistsMsg = `
    73  Error: Inventory information has already been added to the package Kptfile object. Please consider migrating to a standalone resourcegroup object using the 'kpt live migrate' command.
    74  `
    75  
    76  	multipleResourceGroupsMsg = `
    77  Error: Multiple ResourceGroup objects found. Please make sure at most one ResourceGroup object exists within the package.
    78  `
    79  
    80  	//nolint:lll
    81  	inventoryInfoValidationMsg = `
    82  Error: The inventory information is not valid. Please update the information in the ResourceGroup file or provide information with the command line flags. To generate the inventory information the first time, use the 'kpt live init' command.
    83  
    84  Details:
    85  {{- range .err.Violations}}
    86  {{printf "%s" .Reason }}
    87  {{- end}}
    88  `
    89  
    90  	unknownTypesMsg = `
    91  Error: {{ printf "%d" (len .err.GroupVersionKinds) }} resource types could not be found in the cluster or as CRDs among the applied resources.
    92  
    93  Resource types:
    94  {{- range .err.GroupVersionKinds}}
    95  {{ printf "%s" .String }}
    96  {{- end}}
    97  `
    98  )
    99  
   100  // liveErrorResolver is an implementation of the ErrorResolver interface
   101  // that can resolve error types used in the live functionality.
   102  type liveErrorResolver struct{}
   103  
   104  func (*liveErrorResolver) Resolve(err error) (ResolvedResult, bool) {
   105  	var noInventoryObjError *inventory.NoInventoryObjError
   106  	if errors.As(err, &noInventoryObjError) {
   107  		return ResolvedResult{
   108  			Message: ExecuteTemplate(noInventoryObjErrorMsg, map[string]interface{}{
   109  				"err": *noInventoryObjError,
   110  			}),
   111  		}, true
   112  	}
   113  
   114  	var multipleInventoryObjError *inventory.MultipleInventoryObjError
   115  	if errors.As(err, &multipleInventoryObjError) {
   116  		return ResolvedResult{
   117  			Message: ExecuteTemplate(multipleInventoryObjErrorMsg, map[string]interface{}{
   118  				"err": *multipleInventoryObjError,
   119  			}),
   120  		}, true
   121  	}
   122  
   123  	var resourceGroupCRDInstallError *cmdutil.ResourceGroupCRDInstallError
   124  	if errors.As(err, &resourceGroupCRDInstallError) {
   125  		return ResolvedResult{
   126  			Message: ExecuteTemplate(resourceGroupCRDInstallErrorMsg, map[string]interface{}{
   127  				"cause": resourceGroupCRDInstallError.Err.Error(),
   128  			}),
   129  		}, true
   130  	}
   131  
   132  	var noResourceGroupCRDError *cmdutil.NoResourceGroupCRDError
   133  	if errors.As(err, &noResourceGroupCRDError) {
   134  		return ResolvedResult{
   135  			Message: ExecuteTemplate(noResourceGroupCRDMsg, map[string]interface{}{
   136  				"err": *noResourceGroupCRDError,
   137  			}),
   138  		}, true
   139  	}
   140  
   141  	var invExistsError *initialization.InvExistsError
   142  	if errors.As(err, &invExistsError) {
   143  		return ResolvedResult{
   144  			Message: ExecuteTemplate(invInfoAlreadyExistsMsg, map[string]interface{}{
   145  				"err": *invExistsError,
   146  			}),
   147  		}, true
   148  	}
   149  
   150  	var invInfoInRGAlreadyExistsError *initialization.InvInRGExistsError
   151  	if errors.As(err, &invInfoInRGAlreadyExistsError) {
   152  		return ResolvedResult{
   153  			Message: ExecuteTemplate(invInfoInRGAlreadyExistsMsg, map[string]interface{}{
   154  				"err": *invInfoInRGAlreadyExistsError,
   155  			}),
   156  		}, true
   157  	}
   158  
   159  	var invInKfExistsError *initialization.InvInKfExistsError
   160  	if errors.As(err, &invInKfExistsError) {
   161  		return ResolvedResult{
   162  			Message: ExecuteTemplate(invInfoInKfAlreadyExistsMsg, map[string]interface{}{
   163  				"err": *invInKfExistsError,
   164  			}),
   165  		}, true
   166  	}
   167  
   168  	var multipleResourceGroupsError *pkg.MultipleResourceGroupsError
   169  	if errors.As(err, &multipleResourceGroupsError) {
   170  		return ResolvedResult{
   171  			Message: ExecuteTemplate(multipleResourceGroupsMsg, map[string]interface{}{
   172  				"err": *multipleResourceGroupsError,
   173  			}),
   174  		}, true
   175  	}
   176  
   177  	var inventoryInfoValidationError *live.InventoryInfoValidationError
   178  	if errors.As(err, &inventoryInfoValidationError) {
   179  		return ResolvedResult{
   180  			Message: ExecuteTemplate(inventoryInfoValidationMsg, map[string]interface{}{
   181  				"err": *inventoryInfoValidationError,
   182  			}),
   183  		}, true
   184  	}
   185  
   186  	var unknownTypesError *manifestreader.UnknownTypesError
   187  	if errors.As(err, &unknownTypesError) {
   188  		return ResolvedResult{
   189  			Message: ExecuteTemplate(unknownTypesMsg, map[string]interface{}{
   190  				"err": *unknownTypesError,
   191  			}),
   192  		}, true
   193  	}
   194  
   195  	var resultError *common.ResultError
   196  	if errors.As(err, &resultError) {
   197  		return ResolvedResult{
   198  			Message:  "", // Printer summary now replaces ResultError message
   199  			ExitCode: 3,
   200  		}, true
   201  	}
   202  
   203  	return ResolvedResult{}, false
   204  }