1/*
2Copyright 2016 The Kubernetes Authors.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8    http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17// Package types defines types used only by volume components
18package types
19
20import (
21	"errors"
22
23	"k8s.io/apimachinery/pkg/types"
24	"k8s.io/apimachinery/pkg/util/runtime"
25	"k8s.io/mount-utils"
26)
27
28// UniquePodName defines the type to key pods off of
29type UniquePodName types.UID
30
31// UniquePVCName defines the type to key pvc off
32type UniquePVCName types.UID
33
34// GeneratedOperations contains the operation that is created as well as
35// supporting functions required for the operation executor
36type GeneratedOperations struct {
37	// Name of operation - could be used for resetting shared exponential backoff
38	OperationName     string
39	OperationFunc     func() (context OperationContext)
40	EventRecorderFunc func(*error)
41	CompleteFunc      func(CompleteFuncParam)
42}
43
44type OperationContext struct {
45	EventErr    error
46	DetailedErr error
47	Migrated    bool
48}
49
50func NewOperationContext(eventErr, detailedErr error, migrated bool) OperationContext {
51	return OperationContext{
52		EventErr:    eventErr,
53		DetailedErr: detailedErr,
54		Migrated:    migrated,
55	}
56}
57
58type CompleteFuncParam struct {
59	Err      *error
60	Migrated *bool
61}
62
63// Run executes the operations and its supporting functions
64func (o *GeneratedOperations) Run() (eventErr, detailedErr error) {
65	var context OperationContext
66	if o.CompleteFunc != nil {
67		c := CompleteFuncParam{
68			Err:      &context.DetailedErr,
69			Migrated: &context.Migrated,
70		}
71		defer o.CompleteFunc(c)
72	}
73	if o.EventRecorderFunc != nil {
74		defer o.EventRecorderFunc(&eventErr)
75	}
76	// Handle panic, if any, from operationFunc()
77	defer runtime.RecoverFromPanic(&detailedErr)
78
79	context = o.OperationFunc()
80	return context.EventErr, context.DetailedErr
81}
82
83// FailedPrecondition error indicates CSI operation returned failed precondition
84// error
85type FailedPrecondition struct {
86	msg string
87}
88
89func (err *FailedPrecondition) Error() string {
90	return err.msg
91}
92
93// NewFailedPreconditionError returns a new FailedPrecondition error instance
94func NewFailedPreconditionError(msg string) *FailedPrecondition {
95	return &FailedPrecondition{msg: msg}
96}
97
98// IsFailedPreconditionError checks if given error is of type that indicates
99// operation failed with precondition
100func IsFailedPreconditionError(err error) bool {
101	var failedPreconditionError *FailedPrecondition
102	return errors.As(err, &failedPreconditionError)
103}
104
105// TransientOperationFailure indicates operation failed with a transient error
106// and may fix itself when retried.
107type TransientOperationFailure struct {
108	msg string
109}
110
111func (err *TransientOperationFailure) Error() string {
112	return err.msg
113}
114
115// NewTransientOperationFailure creates an instance of TransientOperationFailure error
116func NewTransientOperationFailure(msg string) *TransientOperationFailure {
117	return &TransientOperationFailure{msg: msg}
118}
119
120// UncertainProgressError indicates operation failed with a non-final error
121// and operation may be in-progress in background.
122type UncertainProgressError struct {
123	msg string
124}
125
126func (err *UncertainProgressError) Error() string {
127	return err.msg
128}
129
130// NewUncertainProgressError creates an instance of UncertainProgressError type
131func NewUncertainProgressError(msg string) *UncertainProgressError {
132	return &UncertainProgressError{msg: msg}
133}
134
135// IsOperationFinishedError checks if given error is of type that indicates
136// operation is finished with a FINAL error.
137func IsOperationFinishedError(err error) bool {
138	if _, ok := err.(*UncertainProgressError); ok {
139		return false
140	}
141	if _, ok := err.(*TransientOperationFailure); ok {
142		return false
143	}
144	return true
145}
146
147// IsFilesystemMismatchError checks if mount failed because requested filesystem
148// on PVC and actual filesystem on disk did not match
149func IsFilesystemMismatchError(err error) bool {
150	mountError := mount.MountError{}
151	return errors.As(err, &mountError) && mountError.Type == mount.FilesystemMismatch
152}
153
154// IsUncertainProgressError checks if given error is of type that indicates
155// operation might be in-progress in background.
156func IsUncertainProgressError(err error) bool {
157	if _, ok := err.(*UncertainProgressError); ok {
158		return true
159	}
160	return false
161}
162
163const (
164	// VolumeResizerKey is key that will be used to store resizer used
165	// for resizing PVC. The generated key/value pair will be added
166	// as a annotation to the PVC.
167	VolumeResizerKey = "volume.kubernetes.io/storage-resizer"
168)
169