error.go raw

   1  // Copyright 2022-2025 The sacloud/iaas-api-go Authors
   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 iaas
  16  
  17  import (
  18  	"errors"
  19  	"fmt"
  20  	"net/http"
  21  	"net/url"
  22  )
  23  
  24  // IsNotFoundError 指定のerrorがAPI呼び出し時の404エラーであるか判定
  25  func IsNotFoundError(err error) bool {
  26  	if err == nil {
  27  		return false
  28  	}
  29  
  30  	if apiError, ok := err.(APIError); ok {
  31  		return apiError.ResponseCode() == http.StatusNotFound
  32  	}
  33  
  34  	return false
  35  }
  36  
  37  // IsNoResultsError 指定のerrorがNoResultErrorであるか判定
  38  func IsNoResultsError(err error) bool {
  39  	if err == nil {
  40  		return false
  41  	}
  42  
  43  	_, ok := err.(*NoResultsError)
  44  	return ok
  45  }
  46  
  47  // IsStillCreatingError 指定のerrorがAPI呼び出し時の409エラー、かつエラーコードがstill_creatingであるか判定
  48  func IsStillCreatingError(err error) bool {
  49  	if err == nil {
  50  		return false
  51  	}
  52  
  53  	if apiError, ok := err.(APIError); ok {
  54  		return apiError.ResponseCode() == http.StatusConflict && apiError.Code() == "still_creating"
  55  	}
  56  
  57  	return false
  58  }
  59  
  60  // NoResultsError APIが返した応答に処理すべきデータが含まれていない場合を示すエラー型
  61  type NoResultsError struct {
  62  	error
  63  }
  64  
  65  // NewNoResultsError NoResultErrorを返す
  66  func NewNoResultsError() *NoResultsError {
  67  	return &NoResultsError{error: errors.New("no results")}
  68  }
  69  
  70  // APIErrorResponse APIエラー型
  71  type APIErrorResponse struct {
  72  	IsFatal      bool   `json:"is_fatal,omitempty"`   // IsFatal
  73  	Serial       string `json:"serial,omitempty"`     // Serial
  74  	Status       string `json:"status,omitempty"`     // Status
  75  	ErrorCode    string `json:"error_code,omitempty"` // ErrorCode
  76  	ErrorMessage string `json:"error_msg,omitempty"`  // ErrorMessage
  77  }
  78  
  79  // APIError APIコール時のエラー情報
  80  type APIError interface {
  81  	// errorインターフェースを内包
  82  	error
  83  
  84  	// エラー発生時のレスポンスコード
  85  	ResponseCode() int
  86  
  87  	// エラーコード
  88  	Code() string
  89  
  90  	// エラー発生時のメッセージ
  91  	Message() string
  92  
  93  	// エラー追跡用シリアルコード
  94  	Serial() string
  95  
  96  	// エラー(オリジナル)
  97  	OrigErr() *APIErrorResponse
  98  }
  99  
 100  // NewAPIError APIコール時のエラー情報
 101  func NewAPIError(requestMethod string, requestURL *url.URL, responseCode int, err *APIErrorResponse) APIError {
 102  	return &apiError{
 103  		responseCode: responseCode,
 104  		method:       requestMethod,
 105  		url:          requestURL,
 106  		origErr:      err,
 107  	}
 108  }
 109  
 110  type apiError struct {
 111  	responseCode int
 112  	method       string
 113  	url          *url.URL
 114  	origErr      *APIErrorResponse
 115  }
 116  
 117  // Error errorインターフェース
 118  func (e *apiError) Error() string {
 119  	return fmt.Sprintf("Error in response: %#v", e.origErr)
 120  }
 121  
 122  // ResponseCode エラー発生時のレスポンスコード
 123  func (e *apiError) ResponseCode() int {
 124  	return e.responseCode
 125  }
 126  
 127  // Code エラーコード
 128  func (e *apiError) Code() string {
 129  	if e.origErr != nil {
 130  		return e.origErr.ErrorCode
 131  	}
 132  	return ""
 133  }
 134  
 135  // Message エラー発生時のメッセージ
 136  func (e *apiError) Message() string {
 137  	if e.origErr != nil {
 138  		return e.origErr.ErrorMessage
 139  	}
 140  	return ""
 141  }
 142  
 143  // Serial エラー追跡用シリアルコード
 144  func (e *apiError) Serial() string {
 145  	if e.origErr != nil {
 146  		return e.origErr.Serial
 147  	}
 148  	return ""
 149  }
 150  
 151  // OrigErr エラー(オリジナル)
 152  func (e *apiError) OrigErr() *APIErrorResponse {
 153  	return e.origErr
 154  }
 155