diff --git a/api/crds/v1beta1/backupconfiguration.yaml b/api/crds/v1beta1/backupconfiguration.yaml index 22f4f7d85..9e1fadc99 100644 --- a/api/crds/v1beta1/backupconfiguration.yaml +++ b/api/crds/v1beta1/backupconfiguration.yaml @@ -1960,6 +1960,11 @@ spec: name: type: string type: object + replicas: + description: replicas are the desired number of replicas whose data + should be backed up. If unspecified, defaults to 1. + format: int32 + type: integer snapshotClassName: description: Name of the VolumeSnapshotClass used by the VolumeSnapshot. If not specified, a default snapshot class will be used if it diff --git a/apis/stash/v1beta1/openapi_generated.go b/apis/stash/v1beta1/openapi_generated.go index 831796b1b..27533e9d1 100644 --- a/apis/stash/v1beta1/openapi_generated.go +++ b/apis/stash/v1beta1/openapi_generated.go @@ -13936,6 +13936,13 @@ func schema_stash_apis_stash_v1beta1_BackupTarget(ref common.ReferenceCallback) }, }, }, + "replicas": { + SchemaProps: spec.SchemaProps{ + Description: "replicas are the desired number of replicas whose data should be backed up. If unspecified, defaults to 1.", + Type: []string{"integer"}, + Format: "int32", + }, + }, "snapshotClassName": { SchemaProps: spec.SchemaProps{ Description: "Name of the VolumeSnapshotClass used by the VolumeSnapshot. If not specified, a default snapshot class will be used if it is available. Use this field only if the \"driver\" field is set to \"volumeSnapshotter\".", diff --git a/apis/stash/v1beta1/restore_session_types.go b/apis/stash/v1beta1/restore_session_types.go index 882375c3f..3eb79eb88 100644 --- a/apis/stash/v1beta1/restore_session_types.go +++ b/apis/stash/v1beta1/restore_session_types.go @@ -92,6 +92,7 @@ type HostRestorePhase string const ( HostRestoreSucceeded HostRestorePhase = "Succeeded" HostRestoreFailed HostRestorePhase = "Failed" + HostRestoreUnknown HostRestorePhase = "Unknown" ) type RestoreSessionStatus struct { diff --git a/apis/stash/v1beta1/types.go b/apis/stash/v1beta1/types.go index 48fadffc3..adb2bf218 100644 --- a/apis/stash/v1beta1/types.go +++ b/apis/stash/v1beta1/types.go @@ -26,6 +26,10 @@ type BackupTarget struct { // Specify the volumes that contains the target directories // +optional VolumeMounts []core.VolumeMount `json:"volumeMounts,omitempty"` + //replicas are the desired number of replicas whose data should be backed up. + // If unspecified, defaults to 1. + // +optional + Replicas *int32 `json:"replicas,omitempty"` // Name of the VolumeSnapshotClass used by the VolumeSnapshot. If not specified, a default snapshot class will be used if it is available. // Use this field only if the "driver" field is set to "volumeSnapshotter". // +optional diff --git a/apis/stash/v1beta1/zz_generated.deepcopy.go b/apis/stash/v1beta1/zz_generated.deepcopy.go index 0c6948a3e..0d028f8bf 100644 --- a/apis/stash/v1beta1/zz_generated.deepcopy.go +++ b/apis/stash/v1beta1/zz_generated.deepcopy.go @@ -319,6 +319,11 @@ func (in *BackupTarget) DeepCopyInto(out *BackupTarget) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.Replicas != nil { + in, out := &in.Replicas, &out.Replicas + *out = new(int32) + **out = **in + } return } diff --git a/chart/stash/templates/cluster-role.yaml b/chart/stash/templates/cluster-role.yaml index 40f7b14ff..bea1531ae 100644 --- a/chart/stash/templates/cluster-role.yaml +++ b/chart/stash/templates/cluster-role.yaml @@ -113,3 +113,10 @@ rules: {{- range $x := .Values.additionalPodSecurityPolicies }} - {{ $x }} {{- end }} +- apiGroups: + - snapshot.storage.k8s.io + resources: + - volumesnapshots + - volumesnapshotcontents + - volumesnapshotclasses + verbs: ["create", "get", "list", "watch", "patch"] diff --git a/docs/examples/volume-snapshot/backupconfiguration.yaml b/docs/examples/volume-snapshot/backupconfiguration.yaml index c8d6f4929..b0029893b 100644 --- a/docs/examples/volume-snapshot/backupconfiguration.yaml +++ b/docs/examples/volume-snapshot/backupconfiguration.yaml @@ -5,16 +5,13 @@ metadata: namespace: demo spec: schedule: "* * * * *" - driver: volumeSnapshotter - snapshotClassName: myVolumeSnapshotClassName + driver: VolumeSnapshotter target: ref: apiVersion: apps/v1 - kind: Deployment - name: stash-demo - pvcNames: - - my-first-pvc - - my-second-pvc + kind: StatefulSet + name: web + snapshotClassName: default-snapshot-class retentionPolicy: name: 'keep-last-5' keepLast: 5 diff --git a/docs/examples/volume-snapshot/daemon.yaml b/docs/examples/volume-snapshot/daemon.yaml new file mode 100644 index 000000000..cded2c21e --- /dev/null +++ b/docs/examples/volume-snapshot/daemon.yaml @@ -0,0 +1,44 @@ +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: backup-pvc + namespace: demo +spec: + storageClassName: "standard" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 6Gi +--- +apiVersion: apps/v1 +kind: DaemonSet +metadata: + labels: + app: demo + name: stash-demo + namespace: demo +spec: + selector: + matchLabels: + app: demo + template: + metadata: + labels: + app: demo + name: stash-demo + spec: + containers: + - args: ["touch source/data/sample-file.txt && sleep 3000"] + command: ["/bin/sh", "-c"] + image: busybox + imagePullPolicy: IfNotPresent + name: busybox + volumeMounts: + - mountPath: /source/data + name: source-data + restartPolicy: Always + volumes: + - name: source-data + persistentVolumeClaim: + claimName: backup-pvc diff --git a/docs/examples/volume-snapshot/deployment.yaml b/docs/examples/volume-snapshot/deployment.yaml new file mode 100644 index 000000000..992d79342 --- /dev/null +++ b/docs/examples/volume-snapshot/deployment.yaml @@ -0,0 +1,45 @@ +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: backup-pvc + namespace: demo +spec: + accessModes: + - ReadWriteOnce + storageClassName: "standard" + resources: + requests: + storage: 6Gi +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: stash-demo + name: stash-demo + namespace: demo +spec: + replicas: 1 + selector: + matchLabels: + app: stash-demo + template: + metadata: + labels: + app: stash-demo + name: busybox + spec: + containers: + - args: ["touch source/data/sample-file.txt && sleep 3000"] + command: ["/bin/sh", "-c"] + image: busybox + imagePullPolicy: IfNotPresent + name: busybox + volumeMounts: + - mountPath: /source/data + name: source-data + restartPolicy: Always + volumes: + - name: source-data + persistentVolumeClaim: + claimName: backup-pvc diff --git a/docs/examples/volume-snapshot/pvc.yaml b/docs/examples/volume-snapshot/pvc.yaml new file mode 100644 index 000000000..828da3109 --- /dev/null +++ b/docs/examples/volume-snapshot/pvc.yaml @@ -0,0 +1,12 @@ +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: backup-pvc + namespace: demo +spec: + accessModes: + - ReadWriteOnce + storageClassName: standard + resources: + requests: + storage: 6Gi \ No newline at end of file diff --git a/docs/examples/volume-snapshot/restoresession.yaml b/docs/examples/volume-snapshot/restoresession.yaml index 60ffd3386..ba0899658 100644 --- a/docs/examples/volume-snapshot/restoresession.yaml +++ b/docs/examples/volume-snapshot/restoresession.yaml @@ -1,31 +1,23 @@ apiVersion: stash.appscode.com/v1beta1 kind: RestoreSession metadata: - name: demo-restore-from-volumesnapshot + name: restore namespace: demo spec: - volumeClaimTemplates: - - metadata: - name: my-first-pvc-restored - spec: - accessModes: [ "ReadWriteOnce" ] - storageClassName: "standard" - resources: - requests: - storage: 1Gi - dataSource: - kind: VolumeSnapshot - name: my-first-pvc-snapshot - apiGroup: snapshot.storage.k8s.io - - metadata: - name: my-second-pvc-restored - spec: - accessModes: [ "ReadWriteOnce" ] - storageClassName: "standard" - resources: - requests: - storage: 1Gi - dataSource: - kind: VolumeSnapshot - name: my-second-pvc-snapshot - apiGroup: snapshot.storage.k8s.io + driver: VolumeSnapshotter + target: +# replicas : 3 #for Statefulset + volumeClaimTemplates: + - metadata: + name: pvc + spec: + accessModes: [ "ReadWriteOnce" ] + storageClassName: "standard" + resources: + requests: + storage: 6Gi + dataSource: + kind: VolumeSnapshot +# name: ${CLAIM_NAME}-${POD_ORDINAL}-1558421829 #for Statefulset + name: ${CLAIM_NAME}-1558421829 + apiGroup: snapshot.storage.k8s.io \ No newline at end of file diff --git a/docs/examples/volume-snapshot/statefulset.yaml b/docs/examples/volume-snapshot/statefulset.yaml new file mode 100644 index 000000000..82ef324a3 --- /dev/null +++ b/docs/examples/volume-snapshot/statefulset.yaml @@ -0,0 +1,53 @@ +apiVersion: v1 +kind: Service +metadata: + name: svc + labels: + app: demo + namespace: demo +spec: + ports: + - port: 80 + name: web + clusterIP: None + selector: + app: stash +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: stash-demo + namespace: demo +spec: + selector: + matchLabels: + app: demo + serviceName: svc + replicas: 3 + template: + metadata: + labels: + app: demo # Pod template's label selector + spec: + containers: + - args: ["touch source/data/sample-file.txt && sleep 3000"] + command: ["/bin/sh", "-c"] + name: nginx + image: nginx + ports: + - containerPort: 80 + name: web + volumeMounts: + - name: source-data + mountPath: /source/data + volumeClaimTemplates: + - metadata: + name: source-data + namespace: demo + spec: + accessModes: + - ReadWriteOnce + storageClassName: "standard" + resources: + requests: + storage: 6Gi diff --git a/docs/examples/volume-snapshot/storageclass.yaml b/docs/examples/volume-snapshot/storageclass.yaml new file mode 100644 index 000000000..f77820a37 --- /dev/null +++ b/docs/examples/volume-snapshot/storageclass.yaml @@ -0,0 +1,10 @@ +apiVersion: storage.k8s.io/v1 +kind: StorageClass +metadata: + name: standard +parameters: + type: pd-standard +provisioner: pd.csi.storage.gke.io +reclaimPolicy: Delete +volumeBindingMode: Immediate + diff --git a/docs/examples/volume-snapshot/vs.yaml b/docs/examples/volume-snapshot/vs.yaml new file mode 100644 index 000000000..688b0dd33 --- /dev/null +++ b/docs/examples/volume-snapshot/vs.yaml @@ -0,0 +1,23 @@ +apiVersion: snapshot.storage.k8s.io/v1alpha1 +kind: VolumeSnapshot +metadata: + creationTimestamp: "2019-05-16t06-06-11z" + finalizers: + - snapshot.storage.kubernetes.io/volumesnapshot-protection + generation: 4 + name: pvc-1558421829 + namespace: demo + resourceVersion: "963212" + selfLink: /apis/snapshot.storage.k8s.io/v1alpha1/namespaces/demo/volumesnapshots/pvc-2019-05-16t06-06-09-stash + uid: b47259fe-77a0-11e9-91dc-42010a80001a +spec: + snapshotClassName: default-snapshot-class + snapshotContentName: snapcontent-b47259fe-77a0-11e9-91dc-42010a80001a + source: + apiGroup: null + kind: PersistentVolumeClaim + name: pvc +status: + creationTime: "2019-05-16T06:06:12Z" + readyToUse: true + restoreSize: 6Gi diff --git a/docs/reference/stash.md b/docs/reference/stash.md index 65dc65a5a..99d9fda86 100644 --- a/docs/reference/stash.md +++ b/docs/reference/stash.md @@ -53,6 +53,7 @@ Stash is a Kubernetes operator for restic. For more information, visit here: htt * [stash check](/docs/reference/stash_check.md) - Check restic backup * [stash cli](/docs/reference/stash_cli.md) - Stash CLI * [stash create-backupsession](/docs/reference/stash_create-backupsession.md) - create a BackupSession +* [stash create-vs](/docs/reference/stash_create-vs.md) - Take snapshot of PersistentVolumeClaims * [stash docker](/docs/reference/stash_docker.md) - Run restic commands inside Docker * [stash forget](/docs/reference/stash_forget.md) - Delete snapshots from a restic repository * [stash recover](/docs/reference/stash_recover.md) - Recover restic backup @@ -62,6 +63,7 @@ Stash is a Kubernetes operator for restic. For more information, visit here: htt * [stash restore-mysql](/docs/reference/stash_restore-mysql.md) - Restores MySQL DB Backup * [stash restore-pg](/docs/reference/stash_restore-pg.md) - Restores Postgres DB Backup * [stash restore-pvc](/docs/reference/stash_restore-pvc.md) - Takes a restore of Persistent Volume Claim +* [stash restore-vs](/docs/reference/stash_restore-vs.md) - Restore PVC from VolumeSnapshot * [stash run](/docs/reference/stash_run.md) - Launch Stash Controller * [stash run-backup](/docs/reference/stash_run-backup.md) - Take backup of workload directories * [stash scaledown](/docs/reference/stash_scaledown.md) - Scale down workload diff --git a/docs/reference/stash_create-vs.md b/docs/reference/stash_create-vs.md new file mode 100644 index 000000000..9aab7a87d --- /dev/null +++ b/docs/reference/stash_create-vs.md @@ -0,0 +1,54 @@ +--- +title: Stash Create-Vs +menu: + product_stash_0.8.3: + identifier: stash-create-vs + name: Stash Create-Vs + parent: reference +product_name: stash +menu_name: product_stash_0.8.3 +section_menu_id: reference +--- +## stash create-vs + +Take snapshot of PersistentVolumeClaims + +### Synopsis + +Take snapshot of PersistentVolumeClaims + +``` +stash create-vs [flags] +``` + +### Options + +``` + --backupsession.name string Set BackupSession Name + -h, --help help for create-vs + --kubeconfig string Path to kubeconfig file with authorization information (the master location is set by the master flag). + --master string The address of the Kubernetes API server (overrides any value in kubeconfig) +``` + +### Options inherited from parent commands + +``` + --alsologtostderr log to standard error as well as files + --bypass-validating-webhook-xray if true, bypasses validating webhook xray checks + --enable-analytics Send analytical events to Google Analytics (default true) + --enable-status-subresource If true, uses sub resource for crds. + --log-flush-frequency duration Maximum number of seconds between log flushes (default 5s) + --log_backtrace_at traceLocation when logging hits line file:N, emit a stack trace (default :0) + --log_dir string If non-empty, write log files in this directory + --logtostderr log to standard error instead of files (default true) + --service-name string Stash service name. (default "stash-operator") + --stderrthreshold severity logs at or above this threshold go to stderr + --use-kubeapiserver-fqdn-for-aks if true, uses kube-apiserver FQDN for AKS cluster to workaround https://github.com/Azure/AKS/issues/522 (default true) + -v, --v Level log level for V logs + --vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging +``` + +### SEE ALSO + +* [stash](/docs/reference/stash.md) - Stash by AppsCode - Backup your Kubernetes Volumes + diff --git a/docs/reference/stash_restore-vs.md b/docs/reference/stash_restore-vs.md new file mode 100644 index 000000000..46509876f --- /dev/null +++ b/docs/reference/stash_restore-vs.md @@ -0,0 +1,54 @@ +--- +title: Stash Restore-Vs +menu: + product_stash_0.8.3: + identifier: stash-restore-vs + name: Stash Restore-Vs + parent: reference +product_name: stash +menu_name: product_stash_0.8.3 +section_menu_id: reference +--- +## stash restore-vs + +Restore PVC from VolumeSnapshot + +### Synopsis + +Restore PVC from VolumeSnapshot + +``` +stash restore-vs [flags] +``` + +### Options + +``` + -h, --help help for restore-vs + --kubeconfig string Path to kubeconfig file with authorization information (the master location is set by the master flag). + --master string The address of the Kubernetes API server (overrides any value in kubeconfig) + --restoresession.name string Set Restore Session Name +``` + +### Options inherited from parent commands + +``` + --alsologtostderr log to standard error as well as files + --bypass-validating-webhook-xray if true, bypasses validating webhook xray checks + --enable-analytics Send analytical events to Google Analytics (default true) + --enable-status-subresource If true, uses sub resource for crds. + --log-flush-frequency duration Maximum number of seconds between log flushes (default 5s) + --log_backtrace_at traceLocation when logging hits line file:N, emit a stack trace (default :0) + --log_dir string If non-empty, write log files in this directory + --logtostderr log to standard error instead of files (default true) + --service-name string Stash service name. (default "stash-operator") + --stderrthreshold severity logs at or above this threshold go to stderr + --use-kubeapiserver-fqdn-for-aks if true, uses kube-apiserver FQDN for AKS cluster to workaround https://github.com/Azure/AKS/issues/522 (default true) + -v, --v Level log level for V logs + --vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging +``` + +### SEE ALSO + +* [stash](/docs/reference/stash.md) - Stash by AppsCode - Backup your Kubernetes Volumes + diff --git a/go.mod b/go.mod index 4568e7829..3c0babc12 100644 --- a/go.mod +++ b/go.mod @@ -17,6 +17,7 @@ require ( github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c // indirect github.com/graymeta/stow v0.0.0-00010101000000-000000000000 github.com/json-iterator/go v1.1.6 + github.com/kubernetes-csi/external-snapshotter v1.1.0 github.com/mattn/go-isatty v0.0.8 // indirect github.com/ncw/swift v1.0.47 // indirect github.com/onsi/ginkgo v1.8.0 @@ -30,8 +31,8 @@ require ( github.com/spf13/pflag v1.0.3 github.com/stretchr/testify v1.3.0 golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f // indirect - golang.org/x/net v0.0.0-20190520210107-018c4d40a106 // indirect - golang.org/x/sys v0.0.0-20190520201301-c432e742b0af // indirect + golang.org/x/net v0.0.0-20190522155817-f3200d17e092 // indirect + golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5 // indirect gomodules.xyz/cert v1.0.0 gomodules.xyz/envsubst v0.0.0-20190321051520-c745d52104af google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873 // indirect diff --git a/go.sum b/go.sum index 36b1416e0..3ea3118c2 100644 --- a/go.sum +++ b/go.sum @@ -235,6 +235,8 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kubernetes-csi/external-snapshotter v1.1.0 h1:godlw8BSOac5TMGH2rVPJrmllek3y8wuqd9JsJHgulw= +github.com/kubernetes-csi/external-snapshotter v1.1.0/go.mod h1:oYfxnsuh48V1UDYORl77YQxQbbdokNy7D73phuFpksY= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329 h1:2gxZ0XQIU/5z3Z3bUBu+FXuk2pFbkN6tcwi/pjyaDic= github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= @@ -252,6 +254,7 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= @@ -408,8 +411,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2eP golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c h1:uOCk1iQW6Vc18bnC13MfzScl+wdKBmM9Y9kU7Z83/lw= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190520210107-018c4d40a106 h1:EZofHp/BzEf3j39/+7CX1JvH0WaPG+ikBrqAdAPf+GM= -golang.org/x/net v0.0.0-20190520210107-018c4d40a106/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190522155817-f3200d17e092 h1:4QSRKanuywn15aTZvI/mIDEgPQpswuFndXpOj3rKEco= +golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -434,8 +437,8 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190508100423-12bbe5a7a520 h1:5/ojcKo2vQ2eroPDFcBB9tuc4N42a5njs7UWP2jk3KU= golang.org/x/sys v0.0.0-20190508100423-12bbe5a7a520/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190520201301-c432e742b0af h1:NXfmMfXz6JqGfG3ikSxcz2N93j6DgScr19Oo2uwFu88= -golang.org/x/sys v0.0.0-20190520201301-c432e742b0af/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5 h1:f005F/Jl5JLP036x7QIvUVhNTqxvSYwFIiyOh2q12iU= +golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/hack/deploy/rbac-list.yaml b/hack/deploy/rbac-list.yaml index 3adf5f2cf..e0706a552 100644 --- a/hack/deploy/rbac-list.yaml +++ b/hack/deploy/rbac-list.yaml @@ -60,7 +60,7 @@ rules: - "" resources: - persistentvolumeclaims - verbs: ["get","list","watch"] + verbs: ["get","list","watch", "create", "patch"] - apiGroups: - "" resources: @@ -94,6 +94,7 @@ rules: - clusterroles - roles - rolebindings + - clusterrolebindings verbs: ["get", "create", "delete", "patch"] - apiGroups: - apps.openshift.io @@ -110,6 +111,18 @@ rules: - stash-backupsession-cron - stash-backup-job - stash-restore-job +- apiGroups: + - snapshot.storage.k8s.io + resources: + - volumesnapshots + - volumesnapshotcontents + - volumesnapshotclasses + verbs: ["create", "get", "list", "watch", "patch"] +- apiGroups: + - storage.k8s.io + resources: + - storageclasses + verbs: ["get"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding diff --git a/hack/docker/setup-es.sh b/hack/docker/setup-es.sh index 9bce30111..1ee369501 100755 --- a/hack/docker/setup-es.sh +++ b/hack/docker/setup-es.sh @@ -7,7 +7,7 @@ set -o pipefail GOPATH=$(go env GOPATH) SRC=$GOPATH/src BIN=$GOPATH/bin -REPO_ROOT=$GOPATH/src/github.com/appscode/stash +REPO_ROOT=$GOPATH/src/stash.appscode.dev/stash source "$REPO_ROOT/hack/libbuild/common/lib.sh" source "$REPO_ROOT/hack/libbuild/common/public_image.sh" diff --git a/hack/gencrd/main.go b/hack/gencrd/main.go old mode 100644 new mode 100755 diff --git a/pkg/cmds/create_volumesnapshot.go b/pkg/cmds/create_volumesnapshot.go new file mode 100644 index 000000000..00409a500 --- /dev/null +++ b/pkg/cmds/create_volumesnapshot.go @@ -0,0 +1,219 @@ +package cmds + +import ( + "fmt" + "strings" + "time" + + "github.com/appscode/go/log" + vs "github.com/kubernetes-csi/external-snapshotter/pkg/apis/volumesnapshot/v1alpha1" + vs_cs "github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned" + "github.com/spf13/cobra" + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/tools/clientcmd" + "kmodules.xyz/client-go/meta" + "stash.appscode.dev/stash/apis" + "stash.appscode.dev/stash/apis/stash/v1beta1" + cs "stash.appscode.dev/stash/client/clientset/versioned" + "stash.appscode.dev/stash/pkg/restic" + "stash.appscode.dev/stash/pkg/status" + "stash.appscode.dev/stash/pkg/util" +) + +type VSoption struct { + name string + namespace string + kubeClient kubernetes.Interface + stashClient cs.Interface + snapshotClient vs_cs.Interface +} + +func NewCmdCreateVolumeSnapshot() *cobra.Command { + var ( + masterURL string + kubeconfigPath string + opt = VSoption{ + namespace: meta.Namespace(), + } + ) + + cmd := &cobra.Command{ + Use: "create-vs", + Short: "Take snapshot of PersistentVolumeClaims", + DisableAutoGenTag: true, + Run: func(cmd *cobra.Command, args []string) { + config, err := clientcmd.BuildConfigFromFlags(masterURL, kubeconfigPath) + if err != nil { + log.Fatalf("Could not get Kubernetes config: %s", err) + } + opt.kubeClient = kubernetes.NewForConfigOrDie(config) + opt.stashClient = cs.NewForConfigOrDie(config) + opt.snapshotClient = vs_cs.NewForConfigOrDie(config) + + err = opt.CreateVolumeSnapshot() + if err != nil { + log.Fatal(err) + } + }, + } + cmd.Flags().StringVar(&masterURL, "master", "", "The address of the Kubernetes API server (overrides any value in kubeconfig)") + cmd.Flags().StringVar(&kubeconfigPath, "kubeconfig", "", "Path to kubeconfig file with authorization information (the master location is set by the master flag).") + cmd.Flags().StringVar(&opt.name, "backupsession.name", "", "Set BackupSession Name") + return cmd +} + +func (opt *VSoption) CreateVolumeSnapshot() error { + // Start clock to measure total session duration + startTime := time.Now() + backupSession, err := opt.stashClient.StashV1beta1().BackupSessions(opt.namespace).Get(opt.name, metav1.GetOptions{}) + if err != nil { + return err + } + backupConfiguration, err := opt.stashClient.StashV1beta1().BackupConfigurations(opt.namespace).Get(backupSession.Spec.BackupConfiguration.Name, metav1.GetOptions{}) + if err != nil { + return err + } + if backupConfiguration == nil { + return fmt.Errorf("BackupConfiguration is nil") + } + if backupConfiguration.Spec.Target == nil { + return fmt.Errorf("backupConfiguration target is nil") + } + + kind := backupConfiguration.Spec.Target.Ref.Kind + name := backupConfiguration.Spec.Target.Ref.Name + namespace := backupConfiguration.Namespace + + var ( + pvcList []string + ) + + switch kind { + case apis.KindDeployment: + deployment, err := opt.kubeClient.AppsV1().Deployments(namespace).Get(name, metav1.GetOptions{}) + if err != nil { + return err + } + pvcList = getPVCs(deployment.Spec.Template.Spec.Volumes) + + case apis.KindDaemonSet: + daemon, err := opt.kubeClient.AppsV1().DaemonSets(namespace).Get(name, metav1.GetOptions{}) + if err != nil { + return err + } + pvcList = getPVCs(daemon.Spec.Template.Spec.Volumes) + + case apis.KindReplicationController: + rc, err := opt.kubeClient.CoreV1().ReplicationControllers(namespace).Get(name, metav1.GetOptions{}) + if err != nil { + return err + } + pvcList = getPVCs(rc.Spec.Template.Spec.Volumes) + + case apis.KindReplicaSet: + rs, err := opt.kubeClient.AppsV1().ReplicaSets(namespace).Get(name, metav1.GetOptions{}) + if err != nil { + return err + } + pvcList = getPVCs(rs.Spec.Template.Spec.Volumes) + + case apis.KindStatefulSet: + ss, err := opt.kubeClient.AppsV1().StatefulSets(namespace).Get(name, metav1.GetOptions{}) + if err != nil { + return err + } + pvcList = getPVCsForStatefulset(ss.Spec.VolumeClaimTemplates, ss, backupConfiguration.Spec.Target.Replicas) + + case apis.KindPersistentVolumeClaim: + pvcList = []string{name} + } + + objectMeta := []metav1.ObjectMeta{} + + for _, pvcName := range pvcList { + parts := strings.Split(backupSession.Name, "-") + volumeSnapshot := opt.getVolumeSnapshotDefinition(backupConfiguration, pvcName, parts[len(parts)-1]) + vs, err := opt.snapshotClient.VolumesnapshotV1alpha1().VolumeSnapshots(namespace).Create(&volumeSnapshot) + if err != nil { + return err + } + objectMeta = append(objectMeta, vs.ObjectMeta) + } + + for i, pvcName := range pvcList { + err = util.WaitUntilVolumeSnapshotReady(opt.snapshotClient, objectMeta[i]) + if err != nil { + return err + } + // Update Backup Session + o := status.UpdateStatusOptions{ + KubeClient: opt.kubeClient, + StashClient: opt.stashClient.(*cs.Clientset), + Namespace: opt.namespace, + BackupSession: opt.name, + } + backupOutput := restic.BackupOutput{ + HostBackupStats: v1beta1.HostBackupStats{ + Hostname: pvcName, + Phase: v1beta1.HostBackupSucceeded, + }, + } + // Volume Snapshot complete. Read current time and calculate total backup duration. + endTime := time.Now() + backupOutput.HostBackupStats.Duration = endTime.Sub(startTime).String() + + err = o.UpdatePostBackupStatus(&backupOutput) + if err != nil { + return err + } + } + return nil +} + +func (opt *VSoption) getVolumeSnapshotDefinition(backupConfiguration *v1beta1.BackupConfiguration, pvcName string, timestamp string) (volumeSnapshot vs.VolumeSnapshot) { + return vs.VolumeSnapshot{ + ObjectMeta: metav1.ObjectMeta{ + Name: fmt.Sprintf("%s-%s", pvcName, timestamp), + Namespace: backupConfiguration.Namespace, + }, + Spec: vs.VolumeSnapshotSpec{ + VolumeSnapshotClassName: &backupConfiguration.Spec.Target.VolumeSnapshotClassName, + Source: &corev1.TypedLocalObjectReference{ + Kind: apis.KindPersistentVolumeClaim, + Name: pvcName, + }, + }, + } + +} + +func getPVCs(volList []corev1.Volume) []string { + pvcList := make([]string, 0) + for _, vol := range volList { + if vol.PersistentVolumeClaim != nil { + pvcList = append(pvcList, vol.PersistentVolumeClaim.ClaimName) + } + } + return pvcList +} + +func getPVCsForStatefulset(volList []corev1.PersistentVolumeClaim, ss *appsv1.StatefulSet, replicas *int32) []string { + pvcList := make([]string, 0) + var rep *int32 + if replicas != nil { + rep = replicas + } else { + rep = ss.Spec.Replicas + } + for i := int32(0); i < *rep; i++ { + podName := fmt.Sprintf("%v-%v", ss.Name, i) + for _, vol := range volList { + pvcList = append(pvcList, fmt.Sprintf("%v-%v", vol.Name, podName)) + } + } + return pvcList + +} diff --git a/pkg/cmds/restore_volumesnapshot.go b/pkg/cmds/restore_volumesnapshot.go new file mode 100644 index 000000000..9c24e7892 --- /dev/null +++ b/pkg/cmds/restore_volumesnapshot.go @@ -0,0 +1,204 @@ +package cmds + +import ( + "fmt" + "strconv" + "time" + + "github.com/appscode/go/log" + "github.com/appscode/go/types" + vs_cs "github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned" + "github.com/spf13/cobra" + corev1 "k8s.io/api/core/v1" + storage_api_v1 "k8s.io/api/storage/v1" + kerr "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/tools/clientcmd" + "kmodules.xyz/client-go/meta" + "stash.appscode.dev/stash/apis/stash/v1beta1" + cs "stash.appscode.dev/stash/client/clientset/versioned" + "stash.appscode.dev/stash/pkg/resolve" + "stash.appscode.dev/stash/pkg/restic" + "stash.appscode.dev/stash/pkg/status" + "stash.appscode.dev/stash/pkg/util" +) + +type PVC struct { + podOrdinal *int32 + pvcName string + pvc corev1.PersistentVolumeClaim +} + +func NewCmdRestoreVolumeSnapshot() *cobra.Command { + var ( + masterURL string + kubeconfigPath string + opt = VSoption{ + namespace: meta.Namespace(), + } + ) + + cmd := &cobra.Command{ + Use: "restore-vs", + Short: "Restore PVC from VolumeSnapshot", + DisableAutoGenTag: true, + Run: func(cmd *cobra.Command, args []string) { + config, err := clientcmd.BuildConfigFromFlags(masterURL, kubeconfigPath) + if err != nil { + log.Fatalf("Could not get Kubernetes config: %s", err) + } + opt.kubeClient = kubernetes.NewForConfigOrDie(config) + opt.stashClient = cs.NewForConfigOrDie(config) + opt.snapshotClient = vs_cs.NewForConfigOrDie(config) + + err = opt.RestoreVolumeSnapshot() + if err != nil { + log.Fatal(err) + } + }, + } + cmd.Flags().StringVar(&masterURL, "master", "", "The address of the Kubernetes API server (overrides any value in kubeconfig)") + cmd.Flags().StringVar(&kubeconfigPath, "kubeconfig", "", "Path to kubeconfig file with authorization information (the master location is set by the master flag).") + cmd.Flags().StringVar(&opt.name, "restoresession.name", "", "Set Restore Session Name") + return cmd +} + +func (opt *VSoption) RestoreVolumeSnapshot() error { + // Start clock to measure total session duration + startTime := time.Now() + + restoreSession, err := opt.stashClient.StashV1beta1().RestoreSessions(opt.namespace).Get(opt.name, metav1.GetOptions{}) + if err != nil { + return err + } + + if restoreSession == nil { + return fmt.Errorf("restoreSession is nil") + } + if restoreSession.Spec.Target == nil { + return fmt.Errorf("restoreSession Target is nil") + } + + pvcData := []PVC{} + + if restoreSession.Spec.Target.Replicas == nil { + for _, vol := range restoreSession.Spec.Target.VolumeClaimTemplates { + pvcData = append(pvcData, PVC{pvcName: vol.Name, pvc: vol}) + + } + } else { + for i := int32(0); i < *restoreSession.Spec.Target.Replicas; i++ { + for _, vol := range restoreSession.Spec.Target.VolumeClaimTemplates { + pvcData = append(pvcData, PVC{pvcName: vol.Name, podOrdinal: types.Int32P(i), pvc: vol}) + } + } + + } + + objectMeta := []metav1.ObjectMeta{} + pvcAllReadyExists := false + + for _, data := range pvcData { + pvc := opt.getPVCDefinition(data) + + _, err = opt.kubeClient.CoreV1().PersistentVolumeClaims(opt.namespace).Get(pvc.Name, metav1.GetOptions{}) + if err != nil { + if kerr.IsNotFound(err) { + pvc, err := opt.kubeClient.CoreV1().PersistentVolumeClaims(opt.namespace).Create(pvc) + if err != nil { + return err + } + objectMeta = append(objectMeta, pvc.ObjectMeta) + } else { + return err + } + + } else { + // write failure event for existing PVC + pvcAllReadyExists = true + restoreOutput := restic.RestoreOutput{ + HostRestoreStats: v1beta1.HostRestoreStats{ + Hostname: pvc.Name, + Phase: v1beta1.HostRestoreFailed, + Error: fmt.Sprintf("%s already exixts", pvc.Name), + }, + } + err := opt.updateRestoreSessionStatus(restoreOutput, startTime) + if err != nil { + return err + } + } + } + if pvcAllReadyExists { + return nil + } + + for i, data := range pvcData { + storageClass, err := opt.kubeClient.StorageV1().StorageClasses().Get(types.String(data.pvc.Spec.StorageClassName), metav1.GetOptions{}) + if err != nil { + return err + } + if *storageClass.VolumeBindingMode != storage_api_v1.VolumeBindingImmediate { + // write failure event because of VolumeBindingMode is WaitForFirstConsumer + restoreOutput := restic.RestoreOutput{ + HostRestoreStats: v1beta1.HostRestoreStats{ + Hostname: objectMeta[i].Name, + Phase: v1beta1.HostRestoreUnknown, + Error: fmt.Sprintf("VolumeBindingMode is 'WaitForFirstConsumer'. Stash is unable to decide wheather the restore has succeeded or not as the PVC will not bind with respective PV until any workload mount it."), + }, + } + err := opt.updateRestoreSessionStatus(restoreOutput, startTime) + if err != nil { + return err + } + continue + } + + err = util.WaitUntilPVCReady(opt.kubeClient, objectMeta[i]) + if err != nil { + return err + } + restoreOutput := restic.RestoreOutput{ + HostRestoreStats: v1beta1.HostRestoreStats{ + Hostname: objectMeta[i].Name, + Phase: v1beta1.HostRestoreSucceeded, + }, + } + err = opt.updateRestoreSessionStatus(restoreOutput, startTime) + if err != nil { + return err + } + } + return nil +} + +func (opt *VSoption) getPVCDefinition(data PVC) *corev1.PersistentVolumeClaim { + inputs := make(map[string]string, 0) + if data.podOrdinal == nil { + data.pvc.Name = data.pvcName + } else { + data.pvc.Name = fmt.Sprintf("%v-%v", data.pvcName, *data.podOrdinal) + inputs["POD_ORDINAL"] = strconv.Itoa(int(*data.podOrdinal)) + } + inputs["CLAIM_NAME"] = data.pvcName + err := resolve.ResolvePVCSpec(&data.pvc, inputs) + if err != nil { + return nil + } + return &data.pvc +} + +func (opt *VSoption) updateRestoreSessionStatus(restoreOutput restic.RestoreOutput, startTime time.Time) error { + // Update Backup Session + o := status.UpdateStatusOptions{ + KubeClient: opt.kubeClient, + StashClient: opt.stashClient.(*cs.Clientset), + Namespace: opt.namespace, + RestoreSession: opt.name, + } + // Volume Snapshot complete. Read current time and calculate total backup duration. + endTime := time.Now() + restoreOutput.HostRestoreStats.Duration = endTime.Sub(startTime).String() + return o.UpdatePostRestoreStatus(&restoreOutput) +} diff --git a/pkg/cmds/root.go b/pkg/cmds/root.go index e1a371057..e23b72802 100644 --- a/pkg/cmds/root.go +++ b/pkg/cmds/root.go @@ -77,6 +77,9 @@ func NewRootCmd() *cobra.Command { rootCmd.AddCommand(stash_cli.NewCLICmd()) rootCmd.AddCommand(docker.NewDockerCmd()) + rootCmd.AddCommand(NewCmdCreateVolumeSnapshot()) + rootCmd.AddCommand(NewCmdRestoreVolumeSnapshot()) + rootCmd.AddCommand(NewCmdBackupCluster()) return rootCmd diff --git a/pkg/controller/backup_configuration.go b/pkg/controller/backup_configuration.go index 2c91f3444..d34c93d1f 100644 --- a/pkg/controller/backup_configuration.go +++ b/pkg/controller/backup_configuration.go @@ -82,6 +82,7 @@ func (c *StashController) runBackupConfigurationProcessor(key string) error { } if backupConfiguration.Spec.Target != nil && + backupConfiguration.Spec.Driver != api_v1beta1.VolumeSnapshotter && util.BackupModel(backupConfiguration.Spec.Target.Ref.Kind) == util.ModelSidecar { if err := c.EnsureV1beta1Sidecar(backupConfiguration); err != nil { return err diff --git a/pkg/controller/backup_session.go b/pkg/controller/backup_session.go index cd85ca7a4..5c6990edd 100644 --- a/pkg/controller/backup_session.go +++ b/pkg/controller/backup_session.go @@ -16,6 +16,8 @@ import ( batch_util "kmodules.xyz/client-go/batch/v1" core_util "kmodules.xyz/client-go/core/v1" "kmodules.xyz/client-go/meta" + "kmodules.xyz/client-go/tools/cli" + "kmodules.xyz/client-go/tools/clientcmd" "kmodules.xyz/client-go/tools/queue" "kmodules.xyz/webhook-runtime/admission" hooks "kmodules.xyz/webhook-runtime/admission/v1beta1" @@ -25,13 +27,15 @@ import ( api_v1beta1 "stash.appscode.dev/stash/apis/stash/v1beta1" stash_scheme "stash.appscode.dev/stash/client/clientset/versioned/scheme" stash_util "stash.appscode.dev/stash/client/clientset/versioned/typed/stash/v1beta1/util" + "stash.appscode.dev/stash/pkg/docker" "stash.appscode.dev/stash/pkg/eventer" "stash.appscode.dev/stash/pkg/resolve" "stash.appscode.dev/stash/pkg/util" ) const ( - BackupJobPrefix = "stash-backup-" + BackupJobPrefix = "stash-backup-" + VolumeSnapshotPrefix = "volume-snapshot-" ) func (c *StashController) NewBackupSessionWebhook() hooks.AdmissionHook { @@ -119,6 +123,13 @@ func (c *StashController) runBackupSessionProcessor(key string) error { return c.setBackupSessionSkipped(backupSession, "Backup Configuration is paused") } + if backupConfig.Spec.Target != nil && backupConfig.Spec.Driver == api_v1beta1.VolumeSnapshotter { + err := c.setBackupSessionRunning(backupSession) + if err != nil { + return err + } + return c.ensureVolumeSnapshotterJob(backupConfig, backupSession) + } // skip if backup model is sidecar. // for sidecar model controller inside sidecar will take care of it. if backupConfig.Spec.Target != nil && util.BackupModel(backupConfig.Spec.Target.Ref.Kind) == util.ModelSidecar { @@ -148,11 +159,6 @@ func (c *StashController) ensureBackupJob(backupSession *api_v1beta1.BackupSessi return err } - backupSessionRef, err := reference.GetReference(stash_scheme.Scheme, backupSession) - if err != nil { - return err - } - serviceAccountName := "default" // if RBAC is enabled then ensure respective RBAC stuffs @@ -235,7 +241,7 @@ func (c *StashController) ensureBackupJob(backupSession *api_v1beta1.BackupSessi // create Backup Job _, _, err = batch_util.CreateOrPatchJob(c.kubeClient, jobMeta, func(in *batchv1.Job) *batchv1.Job { // set BackupSession as owner of this Job - core_util.EnsureOwnerReference(&in.ObjectMeta, backupSessionRef) + core_util.EnsureOwnerReference(&in.ObjectMeta, backupConfigRef) in.Labels = map[string]string{ // job controller should not delete this job on completion // use a different label than v1alpha1 job labels to skip deletion from job controller @@ -308,7 +314,7 @@ func (c *StashController) setBackupSessionRunning(backupSession *api_v1beta1.Bac return err } - totalHosts, err := c.getTotalHosts(backupConfig.Spec.Target, backupConfig.Namespace) + totalHosts, err := c.getTotalHosts(backupConfig.Spec.Target, backupConfig.Namespace, backupConfig.Spec.Driver) if err != nil { return err } @@ -394,3 +400,78 @@ func (c *StashController) getBackupSessionPhase(backupSession *api_v1beta1.Backu // backup has been completed successfully return api_v1beta1.BackupSessionSucceeded, nil } + +func (c *StashController) ensureVolumeSnapshotterJob(backupConfig *api_v1beta1.BackupConfiguration, backupSession *api_v1beta1.BackupSession) error { + jobMeta := metav1.ObjectMeta{ + Name: VolumeSnapshotPrefix + backupSession.Name, + Namespace: backupSession.Namespace, + } + + backupConfigRef, err := reference.GetReference(stash_scheme.Scheme, backupConfig) + if err != nil { + return err + } + + serviceAccountName := "default" + //ensure respective RBAC stuffs + //Create new ServiceAccount + serviceAccountName = backupConfig.Name + saMeta := metav1.ObjectMeta{ + Name: serviceAccountName, + Namespace: backupConfig.Namespace, + } + _, _, err = core_util.CreateOrPatchServiceAccount(c.kubeClient, saMeta, func(in *core.ServiceAccount) *core.ServiceAccount { + core_util.EnsureOwnerReference(&in.ObjectMeta, backupConfigRef) + if in.Labels == nil { + in.Labels = map[string]string{} + } + in.Labels[util.LabelApp] = util.AppLabelStash + return in + }) + if err != nil { + return err + } + + err = c.ensureVolumeSnapshotJobRBAC(backupConfigRef, serviceAccountName) + if err != nil { + return err + } + + image := docker.Docker{ + Registry: c.DockerRegistry, + Image: docker.ImageStash, + Tag: c.StashImageTag, + } + + //Create VolumeSnapshotter job + _, _, err = batch_util.CreateOrPatchJob(c.kubeClient, jobMeta, func(in *batchv1.Job) *batchv1.Job { + // set BackupSession as owner of this Job + core_util.EnsureOwnerReference(&in.ObjectMeta, backupConfigRef) + in.Labels = map[string]string{ + // job controller should not delete this job on completion + // use a different label than v1alpha1 job labels to skip deletion from job controller + // TODO: Remove job controller, cleanup backup-session periodically + util.LabelApp: util.AppLabelStashV1Beta1, + } + in.Spec.Template.Spec.Containers = core_util.UpsertContainer( + in.Spec.Template.Spec.Containers, + core.Container{ + Name: util.StashContainer, + ImagePullPolicy: core.PullAlways, + Image: image.ToContainerImage(), + Args: []string{ + "create-vs", + fmt.Sprintf("--backupsession.name=%s", backupSession.Name), + fmt.Sprintf("--enable-status-subresource=%v", apis.EnableStatusSubresource), + fmt.Sprintf("--use-kubeapiserver-fqdn-for-aks=%v", clientcmd.UseKubeAPIServerFQDNForAKS()), + fmt.Sprintf("--enable-analytics=%v", cli.EnableAnalytics), + }, + }) + in.Spec.Template.Spec.RestartPolicy = core.RestartPolicyNever + in.Spec.Template.Spec.ServiceAccountName = serviceAccountName + + return in + }) + + return err +} diff --git a/pkg/controller/rbac_jobs.go b/pkg/controller/rbac_jobs.go index 0fbc58865..228619d14 100644 --- a/pkg/controller/rbac_jobs.go +++ b/pkg/controller/rbac_jobs.go @@ -5,10 +5,12 @@ import ( "strings" "github.com/golang/glog" + crdv1 "github.com/kubernetes-csi/external-snapshotter/pkg/apis/volumesnapshot/v1alpha1" apps "k8s.io/api/apps/v1" core "k8s.io/api/core/v1" policy "k8s.io/api/policy/v1beta1" rbac "k8s.io/api/rbac/v1" + storage_api_v1 "k8s.io/api/storage/v1" kerr "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/tools/clientcmd/api" @@ -24,24 +26,38 @@ import ( ) const ( - SidecarClusterRole = "stash-sidecar" - ScaledownJobRole = "stash-scaledownjob" - RestoreInitContainerClusterRole = "stash-restore-init-container" - RestoreJobClusterRole = "stash-restore-job" - BackupJobClusterRole = "stash-backup-job" - CronJobClusterRole = "stash-cron-job" - KindRole = "Role" - KindClusterRole = "ClusterRole" + SidecarClusterRole = "stash-sidecar" + ScaledownJobRole = "stash-scaledownjob" + RestoreInitContainerClusterRole = "stash-restore-init-container" + RestoreJobClusterRole = "stash-restore-job" + BackupJobClusterRole = "stash-backup-job" + VolumeSnapshotClusterRole = "stash-volumesnapshot-job" + VolumeSnapshotRestoreClusterRole = "stash-volumesnapshot-restore-job" + CronJobClusterRole = "stash-cron-job" + KindRole = "Role" + KindClusterRole = "ClusterRole" + StorageClassClusterRole = "stash-storageclass" ) func (c *StashController) getBackupJobRoleBindingName(name string) string { return name + "-" + BackupJobClusterRole } +func (c *StashController) getVolumesnapshotJobRoleBindingName(name string) string { + return name + "-" + VolumeSnapshotClusterRole +} + func (c *StashController) getRestoreJobRoleBindingName(name string) string { return name + "-" + RestoreJobClusterRole } +func (c *StashController) getVolumeSnapshotRestoreJobRoleBindingName(name string) string { + return name + "-" + VolumeSnapshotRestoreClusterRole +} +func (c *StashController) getStorageClassClusterRoleBindingName(name string) string { + return name + "-" + StorageClassClusterRole +} + func (c *StashController) ensureCronJobRBAC(resource *core.ObjectReference, sa string, psps []string) error { // ensure CronJob cluster role err := c.ensureCronJobClusterRole(psps) @@ -475,6 +491,22 @@ func (c *StashController) ensureRestoreJobRoleBinding(resource *core.ObjectRefer return err } +func (c *StashController) ensureVolumeSnapshotJobRBAC(ref *core.ObjectReference, sa string) error { + // ensure ClusterRole for VolumeSnapshot job + err := c.ensureVolumeSnapshotJobClusterRole() + if err != nil { + return err + } + + // ensure RoleBinding for VolumeSnapshot job + err = c.ensureVolumeSnapshotJobRoleBinding(ref, sa) + if err != nil { + return err + } + + return nil +} + func (c *StashController) ensureBackupJobRBAC(ref *core.ObjectReference, sa string, psps []string) error { // ensure ClusterRole for restore job err := c.ensureBackupJobClusterRole(psps) @@ -563,3 +595,219 @@ func (c *StashController) ensureBackupJobRoleBinding(resource *core.ObjectRefere }) return err } + +func (c *StashController) ensureVolumeSnapshotJobClusterRole() error { + + meta := metav1.ObjectMeta{Name: VolumeSnapshotClusterRole} + _, _, err := rbac_util.CreateOrPatchClusterRole(c.kubeClient, meta, func(in *rbac.ClusterRole) *rbac.ClusterRole { + if in.Labels == nil { + in.Labels = map[string]string{} + } + in.Labels[util.LabelApp] = util.AppLabelStash + + in.Rules = []rbac.PolicyRule{ + { + APIGroups: []string{api_v1beta1.SchemeGroupVersion.Group}, + Resources: []string{"*"}, + Verbs: []string{"*"}, + }, + { + APIGroups: []string{api_v1alpha1.SchemeGroupVersion.Group}, + Resources: []string{"*"}, + Verbs: []string{"*"}, + }, + { + APIGroups: []string{core.GroupName}, + Resources: []string{"events"}, + Verbs: []string{"create"}, + }, + { + APIGroups: []string{apps.GroupName}, + Resources: []string{"deployments", "statefulsets"}, + Verbs: []string{"get", "list"}, + }, + { + APIGroups: []string{apps.GroupName}, + Resources: []string{"daemonsets", "replicasets"}, + Verbs: []string{"get", "list"}, + }, + { + APIGroups: []string{core.GroupName}, + Resources: []string{"replicationcontrollers"}, + Verbs: []string{"get", "list"}, + }, + { + APIGroups: []string{crdv1.GroupName}, + Resources: []string{"volumesnapshots", "volumesnapshotcontents", "volumesnapshotclasses"}, + Verbs: []string{"create", "get", "list", "watch", "patch"}, + }, + } + return in + }) + return err +} + +func (c *StashController) ensureVolumeSnapshotJobRoleBinding(resource *core.ObjectReference, sa string) error { + + meta := metav1.ObjectMeta{ + Namespace: resource.Namespace, + Name: c.getVolumesnapshotJobRoleBindingName(resource.Name), + } + _, _, err := rbac_util.CreateOrPatchRoleBinding(c.kubeClient, meta, func(in *rbac.RoleBinding) *rbac.RoleBinding { + core_util.EnsureOwnerReference(&in.ObjectMeta, resource) + + in.RoleRef = rbac.RoleRef{ + APIGroup: rbac.GroupName, + Kind: KindClusterRole, + Name: VolumeSnapshotClusterRole, + } + in.Subjects = []rbac.Subject{ + { + Kind: rbac.ServiceAccountKind, + Name: sa, + Namespace: resource.Namespace, + }, + } + return in + }) + return err +} + +func (c *StashController) ensureVolumeSnapshotRestoreJobRBAC(ref *core.ObjectReference, sa string) error { + // ensure ClusterRole for restore job + err := c.ensureVolumeSnapshotRestoreJobClusterRole() + if err != nil { + return err + } + + // ensure RoleBinding for restore job + err = c.ensureVolumeSnapshotRestoreJobRoleBinding(ref, sa) + if err != nil { + return err + } + + //ensure storageClass ClusterRole for restore job + err = c.ensureStorageClassClusterRole() + if err != nil { + return err + } + + //ensure storageClass ClusterRoleBinding for restore job + err = c.ensureStorageClassClusterRoleBinding(ref, sa) + if err != nil { + return err + } + + return nil +} + +func (c *StashController) ensureVolumeSnapshotRestoreJobClusterRole() error { + + meta := metav1.ObjectMeta{Name: VolumeSnapshotRestoreClusterRole} + _, _, err := rbac_util.CreateOrPatchClusterRole(c.kubeClient, meta, func(in *rbac.ClusterRole) *rbac.ClusterRole { + if in.Labels == nil { + in.Labels = map[string]string{} + } + in.Labels["app"] = "stash" + + in.Rules = []rbac.PolicyRule{ + { + APIGroups: []string{api_v1beta1.SchemeGroupVersion.Group}, + Resources: []string{"*"}, + Verbs: []string{"*"}, + }, + { + APIGroups: []string{core.GroupName}, + Resources: []string{"events"}, + Verbs: []string{"create"}, + }, + { + APIGroups: []string{core.GroupName}, + Resources: []string{"persistentvolumeclaims"}, + Verbs: []string{"get", "list", "watch", "create", "patch"}, + }, + { + APIGroups: []string{storage_api_v1.GroupName}, + Resources: []string{"storageclasses"}, + Verbs: []string{"get"}, + }, + } + return in + + }) + return err +} + +func (c *StashController) ensureVolumeSnapshotRestoreJobRoleBinding(resource *core.ObjectReference, sa string) error { + + meta := metav1.ObjectMeta{ + Namespace: resource.Namespace, + Name: c.getVolumeSnapshotRestoreJobRoleBindingName(resource.Name), + } + _, _, err := rbac_util.CreateOrPatchRoleBinding(c.kubeClient, meta, func(in *rbac.RoleBinding) *rbac.RoleBinding { + core_util.EnsureOwnerReference(&in.ObjectMeta, resource) + + in.RoleRef = rbac.RoleRef{ + APIGroup: rbac.GroupName, + Kind: "ClusterRole", + Name: VolumeSnapshotRestoreClusterRole, + } + in.Subjects = []rbac.Subject{ + { + Kind: rbac.ServiceAccountKind, + Name: sa, + Namespace: resource.Namespace, + }, + } + return in + }) + return err +} + +func (c *StashController) ensureStorageClassClusterRole() error { + + meta := metav1.ObjectMeta{Name: StorageClassClusterRole} + _, _, err := rbac_util.CreateOrPatchClusterRole(c.kubeClient, meta, func(in *rbac.ClusterRole) *rbac.ClusterRole { + if in.Labels == nil { + in.Labels = map[string]string{} + } + in.Labels["app"] = "stash" + + in.Rules = []rbac.PolicyRule{ + { + APIGroups: []string{storage_api_v1.GroupName}, + Resources: []string{"storageclasses"}, + Verbs: []string{"get"}, + }, + } + return in + + }) + return err +} + +func (c *StashController) ensureStorageClassClusterRoleBinding(resource *core.ObjectReference, sa string) error { + + meta := metav1.ObjectMeta{ + Name: c.getStorageClassClusterRoleBindingName(resource.Name), + Namespace: resource.Namespace, + } + _, _, err := rbac_util.CreateOrPatchClusterRoleBinding(c.kubeClient, meta, func(in *rbac.ClusterRoleBinding) *rbac.ClusterRoleBinding { + core_util.EnsureOwnerReference(&in.ObjectMeta, resource) + + in.RoleRef = rbac.RoleRef{ + APIGroup: rbac.GroupName, + Kind: "ClusterRole", + Name: StorageClassClusterRole, + } + in.Subjects = []rbac.Subject{ + { + Kind: rbac.ServiceAccountKind, + Name: sa, + Namespace: resource.Namespace, + }, + } + return in + }) + return err +} diff --git a/pkg/controller/restore_session.go b/pkg/controller/restore_session.go index 7729aec2b..ef691d31d 100644 --- a/pkg/controller/restore_session.go +++ b/pkg/controller/restore_session.go @@ -16,6 +16,7 @@ import ( batch_util "kmodules.xyz/client-go/batch/v1" core_util "kmodules.xyz/client-go/core/v1" "kmodules.xyz/client-go/meta" + "kmodules.xyz/client-go/tools/cli" "kmodules.xyz/client-go/tools/queue" ofst "kmodules.xyz/offshoot-api/api/v1" "kmodules.xyz/webhook-runtime/admission" @@ -27,6 +28,7 @@ import ( stash_scheme "stash.appscode.dev/stash/client/clientset/versioned/scheme" stash_util "stash.appscode.dev/stash/client/clientset/versioned/typed/stash/v1beta1/util" v1beta1_util "stash.appscode.dev/stash/client/clientset/versioned/typed/stash/v1beta1/util" + "stash.appscode.dev/stash/pkg/docker" "stash.appscode.dev/stash/pkg/eventer" "stash.appscode.dev/stash/pkg/resolve" "stash.appscode.dev/stash/pkg/util" @@ -131,8 +133,10 @@ func (c *StashController) runRestoreSessionProcessor(key string) error { // check whether restore session is completed or running and set it's phase accordingly phase, err := c.getRestoreSessionPhase(restoreSession) - if err != nil || phase == api_v1beta1.RestoreSessionFailed { + if phase == api_v1beta1.RestoreSessionFailed { return c.setRestoreSessionFailed(restoreSession, err) + } else if phase == api_v1beta1.RestoreSessionUnknown { + return c.setRestoreSessionUnknown(restoreSession, err) } else if phase == api_v1beta1.RestoreSessionSucceeded { return c.setRestoreSessionSucceeded(restoreSession) } else if phase == api_v1beta1.RestoreSessionRunning { @@ -140,6 +144,14 @@ func (c *StashController) runRestoreSessionProcessor(key string) error { return nil } + if restoreSession.Spec.Target != nil && restoreSession.Spec.Driver == api_v1beta1.VolumeSnapshotter { + err := c.setRestoreSessionRunning(restoreSession) + if err != nil { + return err + } + return c.ensureVolumeSnapshotterRestoreJob(restoreSession) + } + // if target is kubernetes workload i.e. Deployment, StatefulSet etc. then inject restore init-container if restoreSession.Spec.Target != nil && util.BackupModel(restoreSession.Spec.Target.Ref.Kind) == util.ModelSidecar { // send event to workload controller. workload controller will take care of injecting restore init-container @@ -313,9 +325,33 @@ func (c *StashController) setRestoreSessionFailed(restoreSession *api_v1beta1.Re return err } +func (c *StashController) setRestoreSessionUnknown(restoreSession *api_v1beta1.RestoreSession, jobErr error) error { + + // set RestoreSession phase to "Unknown" + _, err := v1beta1_util.UpdateRestoreSessionStatus(c.stashClient.StashV1beta1(), restoreSession, func(in *api_v1beta1.RestoreSessionStatus) *api_v1beta1.RestoreSessionStatus { + in.Phase = api_v1beta1.RestoreSessionUnknown + return in + }, apis.EnableStatusSubresource) + if err != nil { + return err + } + + // write failure event + _, err = eventer.CreateEvent( + c.kubeClient, + eventer.EventSourceRestoreSessionController, + restoreSession, + core.EventTypeWarning, + eventer.EventReasonRestorePhaseUnknown, + jobErr.Error(), + ) + + return err +} + func (c *StashController) setRestoreSessionRunning(restoreSession *api_v1beta1.RestoreSession) error { - totalHosts, err := c.getTotalHosts(restoreSession.Spec.Target, restoreSession.Namespace) + totalHosts, err := c.getTotalHosts(restoreSession.Spec.Target, restoreSession.Namespace, restoreSession.Spec.Driver) if err != nil { return err } @@ -398,6 +434,86 @@ func (c *StashController) getRestoreSessionPhase(restoreSession *api_v1beta1.Res } } + // check if any of the host phase is "Unknown". if any of their phase is "Unknown", then consider entire restore session phase is unknown. + for _, host := range restoreSession.Status.Stats { + if host.Phase == api_v1beta1.HostRestoreUnknown { + return api_v1beta1.RestoreSessionUnknown, fmt.Errorf("restore phase is 'Unknown' for host: %s. Reason: %s", host.Hostname, host.Error) + } + } + // restore has been completed successfully return api_v1beta1.RestoreSessionSucceeded, nil } + +func (c *StashController) ensureVolumeSnapshotterRestoreJob(restoreSession *api_v1beta1.RestoreSession) error { + jobMeta := metav1.ObjectMeta{ + Name: VolumeSnapshotPrefix + restoreSession.Name, + Namespace: restoreSession.Namespace, + } + + ref, err := reference.GetReference(stash_scheme.Scheme, restoreSession) + if err != nil { + return err + } + + serviceAccountName := "default" + //ensure respective RBAC stuffs + //Create new ServiceAccount + serviceAccountName = restoreSession.Name + saMeta := metav1.ObjectMeta{ + Name: serviceAccountName, + Namespace: restoreSession.Namespace, + } + _, _, err = core_util.CreateOrPatchServiceAccount(c.kubeClient, saMeta, func(in *core.ServiceAccount) *core.ServiceAccount { + core_util.EnsureOwnerReference(&in.ObjectMeta, ref) + if in.Labels == nil { + in.Labels = map[string]string{} + } + in.Labels[util.LabelApp] = util.AppLabelStash + return in + }) + if err != nil { + return err + } + + err = c.ensureVolumeSnapshotRestoreJobRBAC(ref, serviceAccountName) + if err != nil { + return err + } + + image := docker.Docker{ + Registry: c.DockerRegistry, + Image: docker.ImageStash, + Tag: c.StashImageTag, + } + + // create Snapshot Volume Job + _, _, err = batch_util.CreateOrPatchJob(c.kubeClient, jobMeta, func(in *batchv1.Job) *batchv1.Job { + // set BackupSession as owner of this Job + core_util.EnsureOwnerReference(&in.ObjectMeta, ref) + in.Labels = map[string]string{ + // job controller should not delete this job on completion + // use a different label than v1alpha1 job labels to skip deletion from job controller + // TODO: Remove job controller, cleanup backup-session periodically + util.LabelApp: util.AppLabelStashV1Beta1, + } + in.Spec.Template.Spec.Containers = core_util.UpsertContainer( + in.Spec.Template.Spec.Containers, + core.Container{ + Name: util.StashContainer, + ImagePullPolicy: core.PullAlways, + Image: image.ToContainerImage(), + Args: []string{ + "restore-vs", + fmt.Sprintf("--restoresession.name=%s", restoreSession.Name), + fmt.Sprintf("--enable-status-subresource=%v", apis.EnableStatusSubresource), + fmt.Sprintf("--enable-analytics=%v", cli.EnableAnalytics), + }, + }) + in.Spec.Template.Spec.RestartPolicy = core.RestartPolicyNever + in.Spec.Template.Spec.ServiceAccountName = serviceAccountName + + return in + }) + return nil +} diff --git a/pkg/controller/stash.go b/pkg/controller/stash.go index 9a1476624..f52f5de18 100644 --- a/pkg/controller/stash.go +++ b/pkg/controller/stash.go @@ -202,16 +202,20 @@ func hasStashInitContainer(containers []core.Container) bool { return false } -func (c *StashController) getTotalHosts(target interface{}, namespace string) (*int32, error) { +func (c *StashController) getTotalHosts(target interface{}, namespace string, driver api_v1beta1.Snapshotter) (*int32, error) { // for cluster backup/restore, target is nil. in this case, there is only one host var targetRef api_v1beta1.TargetRef + var rep *int32 if target == nil { return types.Int32P(1), nil } switch target.(type) { case *api_v1beta1.BackupTarget: t := target.(*api_v1beta1.BackupTarget) + if t.Replicas != nil { + rep = t.Replicas + } if t == nil { return types.Int32P(1), nil } @@ -222,25 +226,86 @@ func (c *StashController) getTotalHosts(target interface{}, namespace string) (* return types.Int32P(1), nil } targetRef = t.Ref + if driver == api_v1beta1.VolumeSnapshotter { + def := int32(1) + if t.Replicas != nil { + def = types.Int32(t.Replicas) + } + return types.Int32P(def * int32(len(t.VolumeClaimTemplates))), nil + } } - switch targetRef.Kind { - // all replicas of StatefulSet will take backup/restore. so total number of hosts will be number of replicas. - case apis.KindStatefulSet: - ss, err := c.kubeClient.AppsV1().StatefulSets(namespace).Get(targetRef.Name, metav1.GetOptions{}) - if err != nil { - return nil, err + if driver == api_v1beta1.VolumeSnapshotter { + switch targetRef.Kind { + case apis.KindStatefulSet: + ss, err := c.kubeClient.AppsV1().StatefulSets(namespace).Get(targetRef.Name, metav1.GetOptions{}) + if err != nil { + return nil, err + } + if rep != nil { + return types.Int32P(types.Int32(rep) * int32(len(ss.Spec.VolumeClaimTemplates))), err + } + return types.Int32P(types.Int32(ss.Spec.Replicas) * int32(len(ss.Spec.VolumeClaimTemplates))), err + case apis.KindDeployment: + deployment, err := c.kubeClient.AppsV1().Deployments(namespace).Get(targetRef.Name, metav1.GetOptions{}) + if err != nil { + return nil, err + } + return countPVC(deployment.Spec.Template.Spec.Volumes), err + + case apis.KindDaemonSet: + daemon, err := c.kubeClient.AppsV1().DaemonSets(namespace).Get(targetRef.Name, metav1.GetOptions{}) + if err != nil { + return nil, err + } + return countPVC(daemon.Spec.Template.Spec.Volumes), err + + case apis.KindReplicaSet: + rs, err := c.kubeClient.AppsV1().StatefulSets(namespace).Get(targetRef.Name, metav1.GetOptions{}) + if err != nil { + return nil, err + } + return countPVC(rs.Spec.Template.Spec.Volumes), err + + case apis.KindReplicationController: + rc, err := c.kubeClient.CoreV1().ReplicationControllers(namespace).Get(targetRef.Name, metav1.GetOptions{}) + if err != nil { + return nil, err + } + return countPVC(rc.Spec.Template.Spec.Volumes), err + + default: + return types.Int32P(1), nil } - return ss.Spec.Replicas, nil - // all Daemon pod will take backup/restore. so total number of hosts will be number of ready replicas - case apis.KindDaemonSet: - dmn, err := c.kubeClient.AppsV1().DaemonSets(namespace).Get(targetRef.Name, metav1.GetOptions{}) - if err != nil { - return nil, err + } else { + switch targetRef.Kind { + // all replicas of StatefulSet will take backup/restore. so total number of hosts will be number of replicas. + case apis.KindStatefulSet: + ss, err := c.kubeClient.AppsV1().StatefulSets(namespace).Get(targetRef.Name, metav1.GetOptions{}) + if err != nil { + return nil, err + } + return ss.Spec.Replicas, nil + // all Daemon pod will take backup/restore. so total number of hosts will be number of ready replicas + case apis.KindDaemonSet: + dmn, err := c.kubeClient.AppsV1().DaemonSets(namespace).Get(targetRef.Name, metav1.GetOptions{}) + if err != nil { + return nil, err + } + return &dmn.Status.NumberReady, nil + // for all other workloads, only one replica will take backup/restore. so number of total host will be 1 + default: + return types.Int32P(1), nil + } + } +} + +func countPVC(vollist []core.Volume) *int32 { + var count int32 + for _, vol := range vollist { + if vol.PersistentVolumeClaim != nil { + count++ } - return &dmn.Status.NumberReady, nil - // for all other workloads, only one replica will take backup/restore. so number of total host will be 1 - default: - return types.Int32P(1), nil } + return &count } diff --git a/pkg/eventer/recorder.go b/pkg/eventer/recorder.go index d01279b92..13701a1fa 100644 --- a/pkg/eventer/recorder.go +++ b/pkg/eventer/recorder.go @@ -47,6 +47,7 @@ const ( EventReasonInvalidRestoreSession = "InvalidRestoreSession" EventReasonRestoreSessionSucceeded = "RestoreSessionSucceeded" EventReasonRestoreSessionFailed = "RestoreSessionFailedToExecute" + EventReasonRestorePhaseUnknown = "RestoreSession Phase Unknown" EventReasonRestoreJobCreated = "RestoreJobCreated" // RestoreSession events diff --git a/pkg/resolve/task.go b/pkg/resolve/task.go index d80863c3b..c954ac96f 100644 --- a/pkg/resolve/task.go +++ b/pkg/resolve/task.go @@ -223,3 +223,7 @@ func resolveWithInputs(obj interface{}, inputs map[string]string) error { func ResolveBackend(backend *store.Backend, input map[string]string) error { return resolveWithInputs(backend, input) } + +func ResolvePVCSpec(pvc *core.PersistentVolumeClaim, input map[string]string) error { + return resolveWithInputs(pvc, input) +} diff --git a/pkg/status/status.go b/pkg/status/status.go index fb263fff1..172edefe8 100644 --- a/pkg/status/status.go +++ b/pkg/status/status.go @@ -10,6 +10,7 @@ import ( "k8s.io/kubernetes/pkg/apis/core" "stash.appscode.dev/stash/apis" api "stash.appscode.dev/stash/apis/stash/v1alpha1" + api_v1beta1 "stash.appscode.dev/stash/apis/stash/v1beta1" cs "stash.appscode.dev/stash/client/clientset/versioned" stash_util "stash.appscode.dev/stash/client/clientset/versioned/typed/stash/v1alpha1/util" stash_util_v1beta1 "stash.appscode.dev/stash/client/clientset/versioned/typed/stash/v1beta1/util" @@ -97,32 +98,37 @@ func (o UpdateStatusOptions) UpdatePostBackupStatus(backupOutput *restic.BackupO if backupOutput.HostBackupStats.Error != "" { return nil } - - // get repository and update status - repository, err := o.StashClient.StashV1alpha1().Repositories(o.Namespace).Get(o.Repository, metav1.GetOptions{}) + bs, err := o.StashClient.StashV1beta1().BackupConfigurations(o.Namespace).Get(backupSession.Spec.BackupConfiguration.Name, metav1.GetOptions{}) if err != nil { return err } - _, err = stash_util.UpdateRepositoryStatus( - o.StashClient.StashV1alpha1(), - repository, - func(in *api.RepositoryStatus) *api.RepositoryStatus { - // TODO: fix Restic Wrapper - in.Integrity = backupOutput.RepositoryStats.Integrity - in.Size = backupOutput.RepositoryStats.Size - in.SnapshotCount = backupOutput.RepositoryStats.SnapshotCount - in.SnapshotsRemovedOnLastCleanup = backupOutput.RepositoryStats.SnapshotsRemovedOnLastCleanup - - currentTime := metav1.Now() - in.LastBackupTime = ¤tTime - - if in.FirstBackupTime == nil { - in.FirstBackupTime = ¤tTime - } - return in - }, - apis.EnableStatusSubresource, - ) + if bs.Spec.Driver != api_v1beta1.VolumeSnapshotter { + // get repository and update status + repository, err := o.StashClient.StashV1alpha1().Repositories(o.Namespace).Get(o.Repository, metav1.GetOptions{}) + if err != nil { + return err + } + _, err = stash_util.UpdateRepositoryStatus( + o.StashClient.StashV1alpha1(), + repository, + func(in *api.RepositoryStatus) *api.RepositoryStatus { + // TODO: fix Restic Wrapper + in.Integrity = backupOutput.RepositoryStats.Integrity + in.Size = backupOutput.RepositoryStats.Size + in.SnapshotCount = backupOutput.RepositoryStats.SnapshotCount + in.SnapshotsRemovedOnLastCleanup = backupOutput.RepositoryStats.SnapshotsRemovedOnLastCleanup + + currentTime := metav1.Now() + in.LastBackupTime = ¤tTime + + if in.FirstBackupTime == nil { + in.FirstBackupTime = ¤tTime + } + return in + }, + apis.EnableStatusSubresource, + ) + } return err } diff --git a/pkg/util/kubernetes.go b/pkg/util/kubernetes.go index 35cb60748..49d0a1b0f 100644 --- a/pkg/util/kubernetes.go +++ b/pkg/util/kubernetes.go @@ -8,6 +8,7 @@ import ( "github.com/appscode/go/log" "github.com/appscode/go/types" + snapshot_cs "github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned" core "k8s.io/api/core/v1" kerr "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -467,3 +468,21 @@ func WaitUntilDeploymentConfigReady(c oc_cs.Interface, meta metav1.ObjectMeta) e return false, nil }) } + +func WaitUntilVolumeSnapshotReady(c snapshot_cs.Interface, meta metav1.ObjectMeta) error { + return wait.PollImmediate(RetryInterval, 2*time.Hour, func() (bool, error) { + if obj, err := c.VolumesnapshotV1alpha1().VolumeSnapshots(meta.Namespace).Get(meta.Name, metav1.GetOptions{}); err == nil { + return obj.Status.ReadyToUse == true, nil + } + return false, nil + }) +} + +func WaitUntilPVCReady(c kubernetes.Interface, meta metav1.ObjectMeta) error { + return wait.PollImmediate(RetryInterval, 2*time.Hour, func() (bool, error) { + if obj, err := c.CoreV1().PersistentVolumeClaims(meta.Namespace).Get(meta.Name, metav1.GetOptions{}); err == nil { + return obj.Status.Phase == core.ClaimBound, nil + } + return false, nil + }) +} diff --git a/vendor/github.com/kubernetes-csi/external-snapshotter/LICENSE b/vendor/github.com/kubernetes-csi/external-snapshotter/LICENSE new file mode 100644 index 000000000..261eeb9e9 --- /dev/null +++ b/vendor/github.com/kubernetes-csi/external-snapshotter/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/kubernetes-csi/external-snapshotter/pkg/apis/volumesnapshot/v1alpha1/doc.go b/vendor/github.com/kubernetes-csi/external-snapshotter/pkg/apis/volumesnapshot/v1alpha1/doc.go new file mode 100644 index 000000000..fd1b5f86c --- /dev/null +++ b/vendor/github.com/kubernetes-csi/external-snapshotter/pkg/apis/volumesnapshot/v1alpha1/doc.go @@ -0,0 +1,19 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// +k8s:deepcopy-gen=package + +package v1alpha1 diff --git a/vendor/github.com/kubernetes-csi/external-snapshotter/pkg/apis/volumesnapshot/v1alpha1/register.go b/vendor/github.com/kubernetes-csi/external-snapshotter/pkg/apis/volumesnapshot/v1alpha1/register.go new file mode 100644 index 000000000..e7c38b6ba --- /dev/null +++ b/vendor/github.com/kubernetes-csi/external-snapshotter/pkg/apis/volumesnapshot/v1alpha1/register.go @@ -0,0 +1,58 @@ +/* +Copyright 2018 The Kubernetes Authors. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// GroupName is the group name use in this package. +const GroupName = "snapshot.storage.k8s.io" + +var ( + // SchemeBuilder is the new scheme builder + SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) + // AddToScheme adds to scheme + AddToScheme = SchemeBuilder.AddToScheme + // SchemeGroupVersion is the group version used to register these objects. + SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha1"} +) + +// Resource takes an unqualified resource and returns a Group-qualified GroupResource. +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +func init() { + // We only register manually written functions here. The registration of the + // generated functions takes place in the generated files. The separation + // makes the code compile even when the generated files are missing. + SchemeBuilder.Register(addKnownTypes) +} + +// addKnownTypes adds the set of types defined in this package to the supplied scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &VolumeSnapshotClass{}, + &VolumeSnapshotClassList{}, + &VolumeSnapshot{}, + &VolumeSnapshotList{}, + &VolumeSnapshotContent{}, + &VolumeSnapshotContentList{}, + ) + metav1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} diff --git a/vendor/github.com/kubernetes-csi/external-snapshotter/pkg/apis/volumesnapshot/v1alpha1/types.go b/vendor/github.com/kubernetes-csi/external-snapshotter/pkg/apis/volumesnapshot/v1alpha1/types.go new file mode 100644 index 000000000..65c1aafaa --- /dev/null +++ b/vendor/github.com/kubernetes-csi/external-snapshotter/pkg/apis/volumesnapshot/v1alpha1/types.go @@ -0,0 +1,256 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import ( + core_v1 "k8s.io/api/core/v1" + storage "k8s.io/api/storage/v1beta1" + "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +const ( + // VolumeSnapshotContentResourcePlural is "volumesnapshotcontents" + VolumeSnapshotContentResourcePlural = "volumesnapshotcontents" + // VolumeSnapshotResourcePlural is "volumesnapshots" + VolumeSnapshotResourcePlural = "volumesnapshots" + // VolumeSnapshotClassResourcePlural is "volumesnapshotclasses" + VolumeSnapshotClassResourcePlural = "volumesnapshotclasses" +) + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// VolumeSnapshot is a user's request for taking a snapshot. Upon successful creation of the actual +// snapshot by the volume provider it is bound to the corresponding VolumeSnapshotContent. +// Only the VolumeSnapshot object is accessible to the user in the namespace. +type VolumeSnapshot struct { + metav1.TypeMeta `json:",inline"` + // Standard object's metadata. + // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata + // +optional + metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + + // Spec defines the desired characteristics of a snapshot requested by a user. + Spec VolumeSnapshotSpec `json:"spec" protobuf:"bytes,2,opt,name=spec"` + + // Status represents the latest observed state of the snapshot + // +optional + Status VolumeSnapshotStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// VolumeSnapshotList is a list of VolumeSnapshot objects +type VolumeSnapshotList struct { + metav1.TypeMeta `json:",inline"` + // +optional + metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + + // Items is the list of VolumeSnapshots + Items []VolumeSnapshot `json:"items" protobuf:"bytes,2,rep,name=items"` +} + +// VolumeSnapshotSpec describes the common attributes of a volume snapshot +type VolumeSnapshotSpec struct { + // Source has the information about where the snapshot is created from. + // In Alpha version, only PersistentVolumeClaim is supported as the source. + // If not specified, user can create VolumeSnapshotContent and bind it with VolumeSnapshot manually. + // +optional + Source *core_v1.TypedLocalObjectReference `json:"source" protobuf:"bytes,1,opt,name=source"` + + // SnapshotContentName binds the VolumeSnapshot object with the VolumeSnapshotContent + // +optional + SnapshotContentName string `json:"snapshotContentName" protobuf:"bytes,2,opt,name=snapshotContentName"` + + // Name of the VolumeSnapshotClass used by the VolumeSnapshot. If not specified, a default snapshot class will + // be used if it is available. + // +optional + VolumeSnapshotClassName *string `json:"snapshotClassName" protobuf:"bytes,3,opt,name=snapshotClassName"` +} + +// VolumeSnapshotStatus is the status of the VolumeSnapshot +type VolumeSnapshotStatus struct { + // CreationTime is the time the snapshot was successfully created. If it is set, + // it means the snapshot was created; Otherwise the snapshot was not created. + // +optional + CreationTime *metav1.Time `json:"creationTime" protobuf:"bytes,1,opt,name=creationTime"` + + // When restoring volume from the snapshot, the volume size should be equal to or + // larger than the RestoreSize if it is specified. If RestoreSize is set to nil, it means + // that the storage plugin does not have this information available. + // +optional + RestoreSize *resource.Quantity `json:"restoreSize" protobuf:"bytes,2,opt,name=restoreSize"` + + // ReadyToUse is set to true only if the snapshot is ready to use (e.g., finish uploading if + // there is an uploading phase) and also VolumeSnapshot and its VolumeSnapshotContent + // bind correctly with each other. If any of the above condition is not true, ReadyToUse is + // set to false + // +optional + ReadyToUse bool `json:"readyToUse" protobuf:"varint,3,opt,name=readyToUse"` + + // The last error encountered during create snapshot operation, if any. + // This field must only be set by the entity completing the create snapshot + // operation, i.e. the external-snapshotter. + // +optional + Error *storage.VolumeError `json:"error,omitempty" protobuf:"bytes,4,opt,name=error,casttype=VolumeError"` +} + +// +genclient +// +genclient:nonNamespaced +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// VolumeSnapshotClass describes the parameters used by storage system when +// provisioning VolumeSnapshots from PVCs. +// The name of a VolumeSnapshotClass object is significant, and is how users can request a particular class. +type VolumeSnapshotClass struct { + metav1.TypeMeta `json:",inline"` + // Standard object's metadata. + // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata + // +optional + metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + + // Snapshotter is the driver expected to handle this VolumeSnapshotClass. + Snapshotter string `json:"snapshotter" protobuf:"bytes,2,opt,name=snapshotter"` + + // Parameters holds parameters for the snapshotter. + // These values are opaque to the system and are passed directly + // to the snapshotter. + // +optional + Parameters map[string]string `json:"parameters,omitempty" protobuf:"bytes,3,rep,name=parameters"` + + // Optional: what happens to a snapshot content when released from its snapshot. + // The default policy is Delete if not specified. + // +optional + DeletionPolicy *DeletionPolicy `json:"deletionPolicy,omitempty" protobuf:"bytes,4,opt,name=deletionPolicy"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// VolumeSnapshotClassList is a collection of snapshot classes. +type VolumeSnapshotClassList struct { + metav1.TypeMeta `json:",inline"` + // Standard list metadata + // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata + // +optional + metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + + // Items is the list of VolumeSnapshotClasses + Items []VolumeSnapshotClass `json:"items" protobuf:"bytes,2,rep,name=items"` +} + +// +genclient +// +genclient:nonNamespaced +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// VolumeSnapshotContent represents the actual "on-disk" snapshot object +type VolumeSnapshotContent struct { + metav1.TypeMeta `json:",inline"` + // Standard object's metadata. + // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata + // +optional + metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + + // Spec represents the desired state of the snapshot content + Spec VolumeSnapshotContentSpec `json:"spec" protobuf:"bytes,2,opt,name=spec"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// VolumeSnapshotContentList is a list of VolumeSnapshotContent objects +type VolumeSnapshotContentList struct { + metav1.TypeMeta `json:",inline"` + // +optional + metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + + // Items is the list of VolumeSnapshotContents + Items []VolumeSnapshotContent `json:"items" protobuf:"bytes,2,rep,name=items"` +} + +// VolumeSnapshotContentSpec is the spec of the volume snapshot content +type VolumeSnapshotContentSpec struct { + // Source represents the location and type of the volume snapshot + VolumeSnapshotSource `json:",inline" protobuf:"bytes,1,opt,name=volumeSnapshotSource"` + + // VolumeSnapshotRef is part of bi-directional binding between VolumeSnapshot + // and VolumeSnapshotContent. It becomes non-nil when bound. + // +optional + VolumeSnapshotRef *core_v1.ObjectReference `json:"volumeSnapshotRef" protobuf:"bytes,2,opt,name=volumeSnapshotRef"` + + // PersistentVolumeRef represents the PersistentVolume that the snapshot has been + // taken from. It becomes non-nil when VolumeSnapshot and VolumeSnapshotContent are bound. + // +optional + PersistentVolumeRef *core_v1.ObjectReference `json:"persistentVolumeRef" protobuf:"bytes,3,opt,name=persistentVolumeRef"` + + // Name of the VolumeSnapshotClass used by the VolumeSnapshot. If not specified, a default snapshot class will + // be used if it is available. + // +optional + VolumeSnapshotClassName *string `json:"snapshotClassName" protobuf:"bytes,4,opt,name=snapshotClassName"` + + // Optional: what happens to a snapshot content when released from its snapshot. It will be set to Delete by default + // if not specified + // +optional + DeletionPolicy *DeletionPolicy `json:"deletionPolicy" protobuf:"bytes,5,opt,name=deletionPolicy"` +} + +// VolumeSnapshotSource represents the actual location and type of the snapshot. Only one of its members may be specified. +type VolumeSnapshotSource struct { + // CSI (Container Storage Interface) represents storage that handled by an external CSI Volume Driver (Alpha feature). + // +optional + CSI *CSIVolumeSnapshotSource `json:"csiVolumeSnapshotSource,omitempty"` +} + +// CSIVolumeSnapshotSource represents the source from CSI volume snapshot +type CSIVolumeSnapshotSource struct { + // Driver is the name of the driver to use for this snapshot. + // This MUST be the same name returned by the CSI GetPluginName() call for + // that driver. + // Required. + Driver string `json:"driver" protobuf:"bytes,1,opt,name=driver"` + + // SnapshotHandle is the unique snapshot id returned by the CSI volume + // plugin’s CreateSnapshot to refer to the snapshot on all subsequent calls. + // Required. + SnapshotHandle string `json:"snapshotHandle" protobuf:"bytes,2,opt,name=snapshotHandle"` + + // Timestamp when the point-in-time snapshot is taken on the storage + // system. This timestamp will be generated by the CSI volume driver after + // the snapshot is cut. The format of this field should be a Unix nanoseconds + // time encoded as an int64. On Unix, the command `date +%s%N` returns + // the current time in nanoseconds since 1970-01-01 00:00:00 UTC. + // This field is required in the CSI spec but optional here to support static binding. + // +optional + CreationTime *int64 `json:"creationTime,omitempty" protobuf:"varint,3,opt,name=creationTime"` + + // When restoring volume from the snapshot, the volume size should be equal to or + // larger than the RestoreSize if it is specified. If RestoreSize is set to nil, it means + // that the storage plugin does not have this information available. + // +optional + RestoreSize *int64 `json:"restoreSize,omitempty" protobuf:"bytes,4,opt,name=restoreSize"` +} + +// DeletionPolicy describes a policy for end-of-life maintenance of volume snapshot contents +type DeletionPolicy string + +const ( + // VolumeSnapshotContentDelete means the snapshot content will be deleted from Kubernetes on release from its volume snapshot. + VolumeSnapshotContentDelete DeletionPolicy = "Delete" + + // VolumeSnapshotContentRetain means the snapshot will be left in its current state on release from its volume snapshot. + // The default policy is Retain if not specified. + VolumeSnapshotContentRetain DeletionPolicy = "Retain" +) diff --git a/vendor/github.com/kubernetes-csi/external-snapshotter/pkg/apis/volumesnapshot/v1alpha1/zz_generated.deepcopy.go b/vendor/github.com/kubernetes-csi/external-snapshotter/pkg/apis/volumesnapshot/v1alpha1/zz_generated.deepcopy.go new file mode 100644 index 000000000..baed77c6f --- /dev/null +++ b/vendor/github.com/kubernetes-csi/external-snapshotter/pkg/apis/volumesnapshot/v1alpha1/zz_generated.deepcopy.go @@ -0,0 +1,359 @@ +// +build !ignore_autogenerated + +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by deepcopy-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1 "k8s.io/api/core/v1" + v1beta1 "k8s.io/api/storage/v1beta1" + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CSIVolumeSnapshotSource) DeepCopyInto(out *CSIVolumeSnapshotSource) { + *out = *in + if in.CreationTime != nil { + in, out := &in.CreationTime, &out.CreationTime + *out = new(int64) + **out = **in + } + if in.RestoreSize != nil { + in, out := &in.RestoreSize, &out.RestoreSize + *out = new(int64) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CSIVolumeSnapshotSource. +func (in *CSIVolumeSnapshotSource) DeepCopy() *CSIVolumeSnapshotSource { + if in == nil { + return nil + } + out := new(CSIVolumeSnapshotSource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VolumeSnapshot) DeepCopyInto(out *VolumeSnapshot) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeSnapshot. +func (in *VolumeSnapshot) DeepCopy() *VolumeSnapshot { + if in == nil { + return nil + } + out := new(VolumeSnapshot) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VolumeSnapshot) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VolumeSnapshotClass) DeepCopyInto(out *VolumeSnapshotClass) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + if in.Parameters != nil { + in, out := &in.Parameters, &out.Parameters + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.DeletionPolicy != nil { + in, out := &in.DeletionPolicy, &out.DeletionPolicy + *out = new(DeletionPolicy) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeSnapshotClass. +func (in *VolumeSnapshotClass) DeepCopy() *VolumeSnapshotClass { + if in == nil { + return nil + } + out := new(VolumeSnapshotClass) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VolumeSnapshotClass) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VolumeSnapshotClassList) DeepCopyInto(out *VolumeSnapshotClassList) { + *out = *in + out.TypeMeta = in.TypeMeta + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]VolumeSnapshotClass, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeSnapshotClassList. +func (in *VolumeSnapshotClassList) DeepCopy() *VolumeSnapshotClassList { + if in == nil { + return nil + } + out := new(VolumeSnapshotClassList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VolumeSnapshotClassList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VolumeSnapshotContent) DeepCopyInto(out *VolumeSnapshotContent) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeSnapshotContent. +func (in *VolumeSnapshotContent) DeepCopy() *VolumeSnapshotContent { + if in == nil { + return nil + } + out := new(VolumeSnapshotContent) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VolumeSnapshotContent) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VolumeSnapshotContentList) DeepCopyInto(out *VolumeSnapshotContentList) { + *out = *in + out.TypeMeta = in.TypeMeta + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]VolumeSnapshotContent, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeSnapshotContentList. +func (in *VolumeSnapshotContentList) DeepCopy() *VolumeSnapshotContentList { + if in == nil { + return nil + } + out := new(VolumeSnapshotContentList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VolumeSnapshotContentList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VolumeSnapshotContentSpec) DeepCopyInto(out *VolumeSnapshotContentSpec) { + *out = *in + in.VolumeSnapshotSource.DeepCopyInto(&out.VolumeSnapshotSource) + if in.VolumeSnapshotRef != nil { + in, out := &in.VolumeSnapshotRef, &out.VolumeSnapshotRef + *out = new(v1.ObjectReference) + **out = **in + } + if in.PersistentVolumeRef != nil { + in, out := &in.PersistentVolumeRef, &out.PersistentVolumeRef + *out = new(v1.ObjectReference) + **out = **in + } + if in.VolumeSnapshotClassName != nil { + in, out := &in.VolumeSnapshotClassName, &out.VolumeSnapshotClassName + *out = new(string) + **out = **in + } + if in.DeletionPolicy != nil { + in, out := &in.DeletionPolicy, &out.DeletionPolicy + *out = new(DeletionPolicy) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeSnapshotContentSpec. +func (in *VolumeSnapshotContentSpec) DeepCopy() *VolumeSnapshotContentSpec { + if in == nil { + return nil + } + out := new(VolumeSnapshotContentSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VolumeSnapshotList) DeepCopyInto(out *VolumeSnapshotList) { + *out = *in + out.TypeMeta = in.TypeMeta + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]VolumeSnapshot, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeSnapshotList. +func (in *VolumeSnapshotList) DeepCopy() *VolumeSnapshotList { + if in == nil { + return nil + } + out := new(VolumeSnapshotList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VolumeSnapshotList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VolumeSnapshotSource) DeepCopyInto(out *VolumeSnapshotSource) { + *out = *in + if in.CSI != nil { + in, out := &in.CSI, &out.CSI + *out = new(CSIVolumeSnapshotSource) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeSnapshotSource. +func (in *VolumeSnapshotSource) DeepCopy() *VolumeSnapshotSource { + if in == nil { + return nil + } + out := new(VolumeSnapshotSource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VolumeSnapshotSpec) DeepCopyInto(out *VolumeSnapshotSpec) { + *out = *in + if in.Source != nil { + in, out := &in.Source, &out.Source + *out = new(v1.TypedLocalObjectReference) + (*in).DeepCopyInto(*out) + } + if in.VolumeSnapshotClassName != nil { + in, out := &in.VolumeSnapshotClassName, &out.VolumeSnapshotClassName + *out = new(string) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeSnapshotSpec. +func (in *VolumeSnapshotSpec) DeepCopy() *VolumeSnapshotSpec { + if in == nil { + return nil + } + out := new(VolumeSnapshotSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VolumeSnapshotStatus) DeepCopyInto(out *VolumeSnapshotStatus) { + *out = *in + if in.CreationTime != nil { + in, out := &in.CreationTime, &out.CreationTime + *out = (*in).DeepCopy() + } + if in.RestoreSize != nil { + in, out := &in.RestoreSize, &out.RestoreSize + x := (*in).DeepCopy() + *out = &x + } + if in.Error != nil { + in, out := &in.Error, &out.Error + *out = new(v1beta1.VolumeError) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeSnapshotStatus. +func (in *VolumeSnapshotStatus) DeepCopy() *VolumeSnapshotStatus { + if in == nil { + return nil + } + out := new(VolumeSnapshotStatus) + in.DeepCopyInto(out) + return out +} diff --git a/vendor/github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned/clientset.go b/vendor/github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned/clientset.go new file mode 100644 index 000000000..5aefca141 --- /dev/null +++ b/vendor/github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned/clientset.go @@ -0,0 +1,98 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package versioned + +import ( + volumesnapshotv1alpha1 "github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned/typed/volumesnapshot/v1alpha1" + discovery "k8s.io/client-go/discovery" + rest "k8s.io/client-go/rest" + flowcontrol "k8s.io/client-go/util/flowcontrol" +) + +type Interface interface { + Discovery() discovery.DiscoveryInterface + VolumesnapshotV1alpha1() volumesnapshotv1alpha1.VolumesnapshotV1alpha1Interface + // Deprecated: please explicitly pick a version if possible. + Volumesnapshot() volumesnapshotv1alpha1.VolumesnapshotV1alpha1Interface +} + +// Clientset contains the clients for groups. Each group has exactly one +// version included in a Clientset. +type Clientset struct { + *discovery.DiscoveryClient + volumesnapshotV1alpha1 *volumesnapshotv1alpha1.VolumesnapshotV1alpha1Client +} + +// VolumesnapshotV1alpha1 retrieves the VolumesnapshotV1alpha1Client +func (c *Clientset) VolumesnapshotV1alpha1() volumesnapshotv1alpha1.VolumesnapshotV1alpha1Interface { + return c.volumesnapshotV1alpha1 +} + +// Deprecated: Volumesnapshot retrieves the default version of VolumesnapshotClient. +// Please explicitly pick a version. +func (c *Clientset) Volumesnapshot() volumesnapshotv1alpha1.VolumesnapshotV1alpha1Interface { + return c.volumesnapshotV1alpha1 +} + +// Discovery retrieves the DiscoveryClient +func (c *Clientset) Discovery() discovery.DiscoveryInterface { + if c == nil { + return nil + } + return c.DiscoveryClient +} + +// NewForConfig creates a new Clientset for the given config. +func NewForConfig(c *rest.Config) (*Clientset, error) { + configShallowCopy := *c + if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 { + configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst) + } + var cs Clientset + var err error + cs.volumesnapshotV1alpha1, err = volumesnapshotv1alpha1.NewForConfig(&configShallowCopy) + if err != nil { + return nil, err + } + + cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy) + if err != nil { + return nil, err + } + return &cs, nil +} + +// NewForConfigOrDie creates a new Clientset for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *Clientset { + var cs Clientset + cs.volumesnapshotV1alpha1 = volumesnapshotv1alpha1.NewForConfigOrDie(c) + + cs.DiscoveryClient = discovery.NewDiscoveryClientForConfigOrDie(c) + return &cs +} + +// New creates a new Clientset for the given RESTClient. +func New(c rest.Interface) *Clientset { + var cs Clientset + cs.volumesnapshotV1alpha1 = volumesnapshotv1alpha1.New(c) + + cs.DiscoveryClient = discovery.NewDiscoveryClient(c) + return &cs +} diff --git a/vendor/github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned/doc.go b/vendor/github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned/doc.go new file mode 100644 index 000000000..006b79214 --- /dev/null +++ b/vendor/github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned/doc.go @@ -0,0 +1,20 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +// This package has the automatically generated clientset. +package versioned diff --git a/vendor/github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned/scheme/doc.go b/vendor/github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned/scheme/doc.go new file mode 100644 index 000000000..5c5c8debb --- /dev/null +++ b/vendor/github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned/scheme/doc.go @@ -0,0 +1,20 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +// This package contains the scheme of the automatically generated clientset. +package scheme diff --git a/vendor/github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned/scheme/register.go b/vendor/github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned/scheme/register.go new file mode 100644 index 000000000..6215c628f --- /dev/null +++ b/vendor/github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned/scheme/register.go @@ -0,0 +1,56 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package scheme + +import ( + volumesnapshotv1alpha1 "github.com/kubernetes-csi/external-snapshotter/pkg/apis/volumesnapshot/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" + serializer "k8s.io/apimachinery/pkg/runtime/serializer" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" +) + +var Scheme = runtime.NewScheme() +var Codecs = serializer.NewCodecFactory(Scheme) +var ParameterCodec = runtime.NewParameterCodec(Scheme) +var localSchemeBuilder = runtime.SchemeBuilder{ + volumesnapshotv1alpha1.AddToScheme, +} + +// AddToScheme adds all types of this clientset into the given scheme. This allows composition +// of clientsets, like in: +// +// import ( +// "k8s.io/client-go/kubernetes" +// clientsetscheme "k8s.io/client-go/kubernetes/scheme" +// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" +// ) +// +// kclientset, _ := kubernetes.NewForConfig(c) +// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) +// +// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types +// correctly. +var AddToScheme = localSchemeBuilder.AddToScheme + +func init() { + v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"}) + utilruntime.Must(AddToScheme(Scheme)) +} diff --git a/vendor/github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned/typed/volumesnapshot/v1alpha1/doc.go b/vendor/github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned/typed/volumesnapshot/v1alpha1/doc.go new file mode 100644 index 000000000..69ca30111 --- /dev/null +++ b/vendor/github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned/typed/volumesnapshot/v1alpha1/doc.go @@ -0,0 +1,20 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +// This package has the automatically generated typed clients. +package v1alpha1 diff --git a/vendor/github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned/typed/volumesnapshot/v1alpha1/generated_expansion.go b/vendor/github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned/typed/volumesnapshot/v1alpha1/generated_expansion.go new file mode 100644 index 000000000..5c57b1149 --- /dev/null +++ b/vendor/github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned/typed/volumesnapshot/v1alpha1/generated_expansion.go @@ -0,0 +1,25 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +type VolumeSnapshotExpansion interface{} + +type VolumeSnapshotClassExpansion interface{} + +type VolumeSnapshotContentExpansion interface{} diff --git a/vendor/github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned/typed/volumesnapshot/v1alpha1/volumesnapshot.go b/vendor/github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned/typed/volumesnapshot/v1alpha1/volumesnapshot.go new file mode 100644 index 000000000..f383e8073 --- /dev/null +++ b/vendor/github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned/typed/volumesnapshot/v1alpha1/volumesnapshot.go @@ -0,0 +1,191 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "time" + + v1alpha1 "github.com/kubernetes-csi/external-snapshotter/pkg/apis/volumesnapshot/v1alpha1" + scheme "github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned/scheme" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" +) + +// VolumeSnapshotsGetter has a method to return a VolumeSnapshotInterface. +// A group's client should implement this interface. +type VolumeSnapshotsGetter interface { + VolumeSnapshots(namespace string) VolumeSnapshotInterface +} + +// VolumeSnapshotInterface has methods to work with VolumeSnapshot resources. +type VolumeSnapshotInterface interface { + Create(*v1alpha1.VolumeSnapshot) (*v1alpha1.VolumeSnapshot, error) + Update(*v1alpha1.VolumeSnapshot) (*v1alpha1.VolumeSnapshot, error) + UpdateStatus(*v1alpha1.VolumeSnapshot) (*v1alpha1.VolumeSnapshot, error) + Delete(name string, options *v1.DeleteOptions) error + DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error + Get(name string, options v1.GetOptions) (*v1alpha1.VolumeSnapshot, error) + List(opts v1.ListOptions) (*v1alpha1.VolumeSnapshotList, error) + Watch(opts v1.ListOptions) (watch.Interface, error) + Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.VolumeSnapshot, err error) + VolumeSnapshotExpansion +} + +// volumeSnapshots implements VolumeSnapshotInterface +type volumeSnapshots struct { + client rest.Interface + ns string +} + +// newVolumeSnapshots returns a VolumeSnapshots +func newVolumeSnapshots(c *VolumesnapshotV1alpha1Client, namespace string) *volumeSnapshots { + return &volumeSnapshots{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the volumeSnapshot, and returns the corresponding volumeSnapshot object, and an error if there is any. +func (c *volumeSnapshots) Get(name string, options v1.GetOptions) (result *v1alpha1.VolumeSnapshot, err error) { + result = &v1alpha1.VolumeSnapshot{} + err = c.client.Get(). + Namespace(c.ns). + Resource("volumesnapshots"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of VolumeSnapshots that match those selectors. +func (c *volumeSnapshots) List(opts v1.ListOptions) (result *v1alpha1.VolumeSnapshotList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1alpha1.VolumeSnapshotList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("volumesnapshots"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested volumeSnapshots. +func (c *volumeSnapshots) Watch(opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("volumesnapshots"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch() +} + +// Create takes the representation of a volumeSnapshot and creates it. Returns the server's representation of the volumeSnapshot, and an error, if there is any. +func (c *volumeSnapshots) Create(volumeSnapshot *v1alpha1.VolumeSnapshot) (result *v1alpha1.VolumeSnapshot, err error) { + result = &v1alpha1.VolumeSnapshot{} + err = c.client.Post(). + Namespace(c.ns). + Resource("volumesnapshots"). + Body(volumeSnapshot). + Do(). + Into(result) + return +} + +// Update takes the representation of a volumeSnapshot and updates it. Returns the server's representation of the volumeSnapshot, and an error, if there is any. +func (c *volumeSnapshots) Update(volumeSnapshot *v1alpha1.VolumeSnapshot) (result *v1alpha1.VolumeSnapshot, err error) { + result = &v1alpha1.VolumeSnapshot{} + err = c.client.Put(). + Namespace(c.ns). + Resource("volumesnapshots"). + Name(volumeSnapshot.Name). + Body(volumeSnapshot). + Do(). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). + +func (c *volumeSnapshots) UpdateStatus(volumeSnapshot *v1alpha1.VolumeSnapshot) (result *v1alpha1.VolumeSnapshot, err error) { + result = &v1alpha1.VolumeSnapshot{} + err = c.client.Put(). + Namespace(c.ns). + Resource("volumesnapshots"). + Name(volumeSnapshot.Name). + SubResource("status"). + Body(volumeSnapshot). + Do(). + Into(result) + return +} + +// Delete takes name of the volumeSnapshot and deletes it. Returns an error if one occurs. +func (c *volumeSnapshots) Delete(name string, options *v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("volumesnapshots"). + Name(name). + Body(options). + Do(). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *volumeSnapshots) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + var timeout time.Duration + if listOptions.TimeoutSeconds != nil { + timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Namespace(c.ns). + Resource("volumesnapshots"). + VersionedParams(&listOptions, scheme.ParameterCodec). + Timeout(timeout). + Body(options). + Do(). + Error() +} + +// Patch applies the patch and returns the patched volumeSnapshot. +func (c *volumeSnapshots) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.VolumeSnapshot, err error) { + result = &v1alpha1.VolumeSnapshot{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("volumesnapshots"). + SubResource(subresources...). + Name(name). + Body(data). + Do(). + Into(result) + return +} diff --git a/vendor/github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned/typed/volumesnapshot/v1alpha1/volumesnapshot_client.go b/vendor/github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned/typed/volumesnapshot/v1alpha1/volumesnapshot_client.go new file mode 100644 index 000000000..7209839dc --- /dev/null +++ b/vendor/github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned/typed/volumesnapshot/v1alpha1/volumesnapshot_client.go @@ -0,0 +1,100 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1alpha1 "github.com/kubernetes-csi/external-snapshotter/pkg/apis/volumesnapshot/v1alpha1" + "github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned/scheme" + serializer "k8s.io/apimachinery/pkg/runtime/serializer" + rest "k8s.io/client-go/rest" +) + +type VolumesnapshotV1alpha1Interface interface { + RESTClient() rest.Interface + VolumeSnapshotsGetter + VolumeSnapshotClassesGetter + VolumeSnapshotContentsGetter +} + +// VolumesnapshotV1alpha1Client is used to interact with features provided by the volumesnapshot group. +type VolumesnapshotV1alpha1Client struct { + restClient rest.Interface +} + +func (c *VolumesnapshotV1alpha1Client) VolumeSnapshots(namespace string) VolumeSnapshotInterface { + return newVolumeSnapshots(c, namespace) +} + +func (c *VolumesnapshotV1alpha1Client) VolumeSnapshotClasses() VolumeSnapshotClassInterface { + return newVolumeSnapshotClasses(c) +} + +func (c *VolumesnapshotV1alpha1Client) VolumeSnapshotContents() VolumeSnapshotContentInterface { + return newVolumeSnapshotContents(c) +} + +// NewForConfig creates a new VolumesnapshotV1alpha1Client for the given config. +func NewForConfig(c *rest.Config) (*VolumesnapshotV1alpha1Client, error) { + config := *c + if err := setConfigDefaults(&config); err != nil { + return nil, err + } + client, err := rest.RESTClientFor(&config) + if err != nil { + return nil, err + } + return &VolumesnapshotV1alpha1Client{client}, nil +} + +// NewForConfigOrDie creates a new VolumesnapshotV1alpha1Client for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *VolumesnapshotV1alpha1Client { + client, err := NewForConfig(c) + if err != nil { + panic(err) + } + return client +} + +// New creates a new VolumesnapshotV1alpha1Client for the given RESTClient. +func New(c rest.Interface) *VolumesnapshotV1alpha1Client { + return &VolumesnapshotV1alpha1Client{c} +} + +func setConfigDefaults(config *rest.Config) error { + gv := v1alpha1.SchemeGroupVersion + config.GroupVersion = &gv + config.APIPath = "/apis" + config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: scheme.Codecs} + + if config.UserAgent == "" { + config.UserAgent = rest.DefaultKubernetesUserAgent() + } + + return nil +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *VolumesnapshotV1alpha1Client) RESTClient() rest.Interface { + if c == nil { + return nil + } + return c.restClient +} diff --git a/vendor/github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned/typed/volumesnapshot/v1alpha1/volumesnapshotclass.go b/vendor/github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned/typed/volumesnapshot/v1alpha1/volumesnapshotclass.go new file mode 100644 index 000000000..9e48bd945 --- /dev/null +++ b/vendor/github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned/typed/volumesnapshot/v1alpha1/volumesnapshotclass.go @@ -0,0 +1,164 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "time" + + v1alpha1 "github.com/kubernetes-csi/external-snapshotter/pkg/apis/volumesnapshot/v1alpha1" + scheme "github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned/scheme" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" +) + +// VolumeSnapshotClassesGetter has a method to return a VolumeSnapshotClassInterface. +// A group's client should implement this interface. +type VolumeSnapshotClassesGetter interface { + VolumeSnapshotClasses() VolumeSnapshotClassInterface +} + +// VolumeSnapshotClassInterface has methods to work with VolumeSnapshotClass resources. +type VolumeSnapshotClassInterface interface { + Create(*v1alpha1.VolumeSnapshotClass) (*v1alpha1.VolumeSnapshotClass, error) + Update(*v1alpha1.VolumeSnapshotClass) (*v1alpha1.VolumeSnapshotClass, error) + Delete(name string, options *v1.DeleteOptions) error + DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error + Get(name string, options v1.GetOptions) (*v1alpha1.VolumeSnapshotClass, error) + List(opts v1.ListOptions) (*v1alpha1.VolumeSnapshotClassList, error) + Watch(opts v1.ListOptions) (watch.Interface, error) + Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.VolumeSnapshotClass, err error) + VolumeSnapshotClassExpansion +} + +// volumeSnapshotClasses implements VolumeSnapshotClassInterface +type volumeSnapshotClasses struct { + client rest.Interface +} + +// newVolumeSnapshotClasses returns a VolumeSnapshotClasses +func newVolumeSnapshotClasses(c *VolumesnapshotV1alpha1Client) *volumeSnapshotClasses { + return &volumeSnapshotClasses{ + client: c.RESTClient(), + } +} + +// Get takes name of the volumeSnapshotClass, and returns the corresponding volumeSnapshotClass object, and an error if there is any. +func (c *volumeSnapshotClasses) Get(name string, options v1.GetOptions) (result *v1alpha1.VolumeSnapshotClass, err error) { + result = &v1alpha1.VolumeSnapshotClass{} + err = c.client.Get(). + Resource("volumesnapshotclasses"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of VolumeSnapshotClasses that match those selectors. +func (c *volumeSnapshotClasses) List(opts v1.ListOptions) (result *v1alpha1.VolumeSnapshotClassList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1alpha1.VolumeSnapshotClassList{} + err = c.client.Get(). + Resource("volumesnapshotclasses"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested volumeSnapshotClasses. +func (c *volumeSnapshotClasses) Watch(opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Resource("volumesnapshotclasses"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch() +} + +// Create takes the representation of a volumeSnapshotClass and creates it. Returns the server's representation of the volumeSnapshotClass, and an error, if there is any. +func (c *volumeSnapshotClasses) Create(volumeSnapshotClass *v1alpha1.VolumeSnapshotClass) (result *v1alpha1.VolumeSnapshotClass, err error) { + result = &v1alpha1.VolumeSnapshotClass{} + err = c.client.Post(). + Resource("volumesnapshotclasses"). + Body(volumeSnapshotClass). + Do(). + Into(result) + return +} + +// Update takes the representation of a volumeSnapshotClass and updates it. Returns the server's representation of the volumeSnapshotClass, and an error, if there is any. +func (c *volumeSnapshotClasses) Update(volumeSnapshotClass *v1alpha1.VolumeSnapshotClass) (result *v1alpha1.VolumeSnapshotClass, err error) { + result = &v1alpha1.VolumeSnapshotClass{} + err = c.client.Put(). + Resource("volumesnapshotclasses"). + Name(volumeSnapshotClass.Name). + Body(volumeSnapshotClass). + Do(). + Into(result) + return +} + +// Delete takes name of the volumeSnapshotClass and deletes it. Returns an error if one occurs. +func (c *volumeSnapshotClasses) Delete(name string, options *v1.DeleteOptions) error { + return c.client.Delete(). + Resource("volumesnapshotclasses"). + Name(name). + Body(options). + Do(). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *volumeSnapshotClasses) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + var timeout time.Duration + if listOptions.TimeoutSeconds != nil { + timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Resource("volumesnapshotclasses"). + VersionedParams(&listOptions, scheme.ParameterCodec). + Timeout(timeout). + Body(options). + Do(). + Error() +} + +// Patch applies the patch and returns the patched volumeSnapshotClass. +func (c *volumeSnapshotClasses) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.VolumeSnapshotClass, err error) { + result = &v1alpha1.VolumeSnapshotClass{} + err = c.client.Patch(pt). + Resource("volumesnapshotclasses"). + SubResource(subresources...). + Name(name). + Body(data). + Do(). + Into(result) + return +} diff --git a/vendor/github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned/typed/volumesnapshot/v1alpha1/volumesnapshotcontent.go b/vendor/github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned/typed/volumesnapshot/v1alpha1/volumesnapshotcontent.go new file mode 100644 index 000000000..11aac5159 --- /dev/null +++ b/vendor/github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned/typed/volumesnapshot/v1alpha1/volumesnapshotcontent.go @@ -0,0 +1,164 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "time" + + v1alpha1 "github.com/kubernetes-csi/external-snapshotter/pkg/apis/volumesnapshot/v1alpha1" + scheme "github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned/scheme" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" +) + +// VolumeSnapshotContentsGetter has a method to return a VolumeSnapshotContentInterface. +// A group's client should implement this interface. +type VolumeSnapshotContentsGetter interface { + VolumeSnapshotContents() VolumeSnapshotContentInterface +} + +// VolumeSnapshotContentInterface has methods to work with VolumeSnapshotContent resources. +type VolumeSnapshotContentInterface interface { + Create(*v1alpha1.VolumeSnapshotContent) (*v1alpha1.VolumeSnapshotContent, error) + Update(*v1alpha1.VolumeSnapshotContent) (*v1alpha1.VolumeSnapshotContent, error) + Delete(name string, options *v1.DeleteOptions) error + DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error + Get(name string, options v1.GetOptions) (*v1alpha1.VolumeSnapshotContent, error) + List(opts v1.ListOptions) (*v1alpha1.VolumeSnapshotContentList, error) + Watch(opts v1.ListOptions) (watch.Interface, error) + Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.VolumeSnapshotContent, err error) + VolumeSnapshotContentExpansion +} + +// volumeSnapshotContents implements VolumeSnapshotContentInterface +type volumeSnapshotContents struct { + client rest.Interface +} + +// newVolumeSnapshotContents returns a VolumeSnapshotContents +func newVolumeSnapshotContents(c *VolumesnapshotV1alpha1Client) *volumeSnapshotContents { + return &volumeSnapshotContents{ + client: c.RESTClient(), + } +} + +// Get takes name of the volumeSnapshotContent, and returns the corresponding volumeSnapshotContent object, and an error if there is any. +func (c *volumeSnapshotContents) Get(name string, options v1.GetOptions) (result *v1alpha1.VolumeSnapshotContent, err error) { + result = &v1alpha1.VolumeSnapshotContent{} + err = c.client.Get(). + Resource("volumesnapshotcontents"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of VolumeSnapshotContents that match those selectors. +func (c *volumeSnapshotContents) List(opts v1.ListOptions) (result *v1alpha1.VolumeSnapshotContentList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1alpha1.VolumeSnapshotContentList{} + err = c.client.Get(). + Resource("volumesnapshotcontents"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested volumeSnapshotContents. +func (c *volumeSnapshotContents) Watch(opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Resource("volumesnapshotcontents"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch() +} + +// Create takes the representation of a volumeSnapshotContent and creates it. Returns the server's representation of the volumeSnapshotContent, and an error, if there is any. +func (c *volumeSnapshotContents) Create(volumeSnapshotContent *v1alpha1.VolumeSnapshotContent) (result *v1alpha1.VolumeSnapshotContent, err error) { + result = &v1alpha1.VolumeSnapshotContent{} + err = c.client.Post(). + Resource("volumesnapshotcontents"). + Body(volumeSnapshotContent). + Do(). + Into(result) + return +} + +// Update takes the representation of a volumeSnapshotContent and updates it. Returns the server's representation of the volumeSnapshotContent, and an error, if there is any. +func (c *volumeSnapshotContents) Update(volumeSnapshotContent *v1alpha1.VolumeSnapshotContent) (result *v1alpha1.VolumeSnapshotContent, err error) { + result = &v1alpha1.VolumeSnapshotContent{} + err = c.client.Put(). + Resource("volumesnapshotcontents"). + Name(volumeSnapshotContent.Name). + Body(volumeSnapshotContent). + Do(). + Into(result) + return +} + +// Delete takes name of the volumeSnapshotContent and deletes it. Returns an error if one occurs. +func (c *volumeSnapshotContents) Delete(name string, options *v1.DeleteOptions) error { + return c.client.Delete(). + Resource("volumesnapshotcontents"). + Name(name). + Body(options). + Do(). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *volumeSnapshotContents) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + var timeout time.Duration + if listOptions.TimeoutSeconds != nil { + timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Resource("volumesnapshotcontents"). + VersionedParams(&listOptions, scheme.ParameterCodec). + Timeout(timeout). + Body(options). + Do(). + Error() +} + +// Patch applies the patch and returns the patched volumeSnapshotContent. +func (c *volumeSnapshotContents) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.VolumeSnapshotContent, err error) { + result = &v1alpha1.VolumeSnapshotContent{} + err = c.client.Patch(pt). + Resource("volumesnapshotcontents"). + SubResource(subresources...). + Name(name). + Body(data). + Do(). + Into(result) + return +} diff --git a/vendor/golang.org/x/sys/windows/security_windows.go b/vendor/golang.org/x/sys/windows/security_windows.go index f119a4adf..e9d26bee3 100644 --- a/vendor/golang.org/x/sys/windows/security_windows.go +++ b/vendor/golang.org/x/sys/windows/security_windows.go @@ -583,9 +583,7 @@ func (tml *Tokenmandatorylabel) Size() uint32 { // Authorization Functions //sys checkTokenMembership(tokenHandle Token, sidToCheck *SID, isMember *int32) (err error) = advapi32.CheckTokenMembership //sys OpenProcessToken(process Handle, access uint32, token *Token) (err error) = advapi32.OpenProcessToken -//sys GetCurrentThreadToken() (token Token) = advapi32.GetCurrentThreadToken //sys OpenThreadToken(thread Handle, access uint32, openAsSelf bool, token *Token) (err error) = advapi32.OpenThreadToken -//sys GetCurrentProcessToken() (token Token) = advapi32.GetCurrentProcessToken //sys ImpersonateSelf(impersonationlevel uint32) (err error) = advapi32.ImpersonateSelf //sys RevertToSelf() (err error) = advapi32.RevertToSelf //sys SetThreadToken(thread *Handle, token Token) (err error) = advapi32.SetThreadToken @@ -608,7 +606,9 @@ func (tml *Tokenmandatorylabel) Size() uint32 { type Token Handle // OpenCurrentProcessToken opens the access token -// associated with current process. +// associated with current process. It is a real +// token that needs to be closed, unlike +// GetCurrentProcessToken. func OpenCurrentProcessToken() (Token, error) { p, e := GetCurrentProcess() if e != nil { @@ -622,6 +622,27 @@ func OpenCurrentProcessToken() (Token, error) { return t, nil } +// GetCurrentProcessToken returns the access token associated with +// the current process. It is a pseudo token that does not need +// to be closed. +func GetCurrentProcessToken() Token { + return Token(^uintptr(4 - 1)) +} + +// GetCurrentThreadToken return the access token associated with +// the current thread. It is a pseudo token that does not need +// to be closed. +func GetCurrentThreadToken() Token { + return Token(^uintptr(5 - 1)) +} + +// GetCurrentThreadEffectiveToken returns the effective access token +// associated with the current thread. It is a pseudo token that does +// not need to be closed. +func GetCurrentThreadEffectiveToken() Token { + return Token(^uintptr(6 - 1)) +} + // Close releases access to access token. func (t Token) Close() error { return CloseHandle(Handle(t)) diff --git a/vendor/golang.org/x/sys/windows/service.go b/vendor/golang.org/x/sys/windows/service.go index 237e06f82..9a59b42f6 100644 --- a/vendor/golang.org/x/sys/windows/service.go +++ b/vendor/golang.org/x/sys/windows/service.go @@ -85,19 +85,33 @@ const ( SERVICE_INACTIVE = 2 SERVICE_STATE_ALL = 3 - SERVICE_QUERY_CONFIG = 1 - SERVICE_CHANGE_CONFIG = 2 - SERVICE_QUERY_STATUS = 4 - SERVICE_ENUMERATE_DEPENDENTS = 8 - SERVICE_START = 16 - SERVICE_STOP = 32 - SERVICE_PAUSE_CONTINUE = 64 - SERVICE_INTERROGATE = 128 - SERVICE_USER_DEFINED_CONTROL = 256 - SERVICE_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SERVICE_QUERY_CONFIG | SERVICE_CHANGE_CONFIG | SERVICE_QUERY_STATUS | SERVICE_ENUMERATE_DEPENDENTS | SERVICE_START | SERVICE_STOP | SERVICE_PAUSE_CONTINUE | SERVICE_INTERROGATE | SERVICE_USER_DEFINED_CONTROL + SERVICE_QUERY_CONFIG = 1 + SERVICE_CHANGE_CONFIG = 2 + SERVICE_QUERY_STATUS = 4 + SERVICE_ENUMERATE_DEPENDENTS = 8 + SERVICE_START = 16 + SERVICE_STOP = 32 + SERVICE_PAUSE_CONTINUE = 64 + SERVICE_INTERROGATE = 128 + SERVICE_USER_DEFINED_CONTROL = 256 + SERVICE_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SERVICE_QUERY_CONFIG | SERVICE_CHANGE_CONFIG | SERVICE_QUERY_STATUS | SERVICE_ENUMERATE_DEPENDENTS | SERVICE_START | SERVICE_STOP | SERVICE_PAUSE_CONTINUE | SERVICE_INTERROGATE | SERVICE_USER_DEFINED_CONTROL + SERVICE_RUNS_IN_SYSTEM_PROCESS = 1 - SERVICE_CONFIG_DESCRIPTION = 1 - SERVICE_CONFIG_FAILURE_ACTIONS = 2 + + SERVICE_CONFIG_DESCRIPTION = 1 + SERVICE_CONFIG_FAILURE_ACTIONS = 2 + SERVICE_CONFIG_DELAYED_AUTO_START_INFO = 3 + SERVICE_CONFIG_FAILURE_ACTIONS_FLAG = 4 + SERVICE_CONFIG_SERVICE_SID_INFO = 5 + SERVICE_CONFIG_REQUIRED_PRIVILEGES_INFO = 6 + SERVICE_CONFIG_PRESHUTDOWN_INFO = 7 + SERVICE_CONFIG_TRIGGER_INFO = 8 + SERVICE_CONFIG_PREFERRED_NODE = 9 + SERVICE_CONFIG_LAUNCH_PROTECTED = 12 + + SERVICE_SID_TYPE_NONE = 0 + SERVICE_SID_TYPE_UNRESTRICTED = 1 + SERVICE_SID_TYPE_RESTRICTED = 2 | SERVICE_SID_TYPE_UNRESTRICTED SC_ENUM_PROCESS_INFO = 0 diff --git a/vendor/golang.org/x/sys/windows/zsyscall_windows.go b/vendor/golang.org/x/sys/windows/zsyscall_windows.go index 624d02fad..2a0f39698 100644 --- a/vendor/golang.org/x/sys/windows/zsyscall_windows.go +++ b/vendor/golang.org/x/sys/windows/zsyscall_windows.go @@ -259,9 +259,7 @@ var ( procEqualSid = modadvapi32.NewProc("EqualSid") procCheckTokenMembership = modadvapi32.NewProc("CheckTokenMembership") procOpenProcessToken = modadvapi32.NewProc("OpenProcessToken") - procGetCurrentThreadToken = modadvapi32.NewProc("GetCurrentThreadToken") procOpenThreadToken = modadvapi32.NewProc("OpenThreadToken") - procGetCurrentProcessToken = modadvapi32.NewProc("GetCurrentProcessToken") procImpersonateSelf = modadvapi32.NewProc("ImpersonateSelf") procRevertToSelf = modadvapi32.NewProc("RevertToSelf") procSetThreadToken = modadvapi32.NewProc("SetThreadToken") @@ -2824,12 +2822,6 @@ func OpenProcessToken(process Handle, access uint32, token *Token) (err error) { return } -func GetCurrentThreadToken() (token Token) { - r0, _, _ := syscall.Syscall(procGetCurrentThreadToken.Addr(), 0, 0, 0, 0) - token = Token(r0) - return -} - func OpenThreadToken(thread Handle, access uint32, openAsSelf bool, token *Token) (err error) { var _p0 uint32 if openAsSelf { @@ -2848,12 +2840,6 @@ func OpenThreadToken(thread Handle, access uint32, openAsSelf bool, token *Token return } -func GetCurrentProcessToken() (token Token) { - r0, _, _ := syscall.Syscall(procGetCurrentProcessToken.Addr(), 0, 0, 0, 0) - token = Token(r0) - return -} - func ImpersonateSelf(impersonationlevel uint32) (err error) { r1, _, e1 := syscall.Syscall(procImpersonateSelf.Addr(), 1, uintptr(impersonationlevel), 0, 0) if r1 == 0 { diff --git a/vendor/modules.txt b/vendor/modules.txt index 42c97cbb2..cdfbf9228 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -194,6 +194,11 @@ github.com/jmespath/go-jmespath github.com/jpillora/go-ogle-analytics # github.com/json-iterator/go v1.1.6 github.com/json-iterator/go +# github.com/kubernetes-csi/external-snapshotter v1.1.0 +github.com/kubernetes-csi/external-snapshotter/pkg/apis/volumesnapshot/v1alpha1 +github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned +github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned/typed/volumesnapshot/v1alpha1 +github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned/scheme # github.com/mailru/easyjson v0.0.0-20190403194419-1ea4449da983 github.com/mailru/easyjson/jlexer github.com/mailru/easyjson/jwriter @@ -307,7 +312,7 @@ go.opencensus.io/resource go.opencensus.io # golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f golang.org/x/crypto/ssh/terminal -# golang.org/x/net v0.0.0-20190520210107-018c4d40a106 +# golang.org/x/net v0.0.0-20190522155817-f3200d17e092 golang.org/x/net/http2 golang.org/x/net/http/httpguts golang.org/x/net/http2/hpack @@ -326,7 +331,7 @@ golang.org/x/oauth2/google golang.org/x/oauth2/internal golang.org/x/oauth2/jws golang.org/x/oauth2/jwt -# golang.org/x/sys v0.0.0-20190520201301-c432e742b0af +# golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5 golang.org/x/sys/unix golang.org/x/sys/windows # golang.org/x/text v0.3.2 @@ -435,9 +440,10 @@ gopkg.in/yaml.v2 # k8s.io/api v0.0.0-20190503110853-61630f889b3c => k8s.io/api v0.0.0-20190313235455-40a48860b5ab k8s.io/api/core/v1 k8s.io/api/rbac/v1 +k8s.io/api/apps/v1 +k8s.io/api/storage/v1 k8s.io/api/batch/v1 k8s.io/api/admission/v1beta1 -k8s.io/api/apps/v1 k8s.io/api/apps/v1beta1 k8s.io/api/apps/v1beta2 k8s.io/api/batch/v1beta1 @@ -467,7 +473,6 @@ k8s.io/api/scheduling/v1 k8s.io/api/scheduling/v1alpha1 k8s.io/api/scheduling/v1beta1 k8s.io/api/settings/v1alpha1 -k8s.io/api/storage/v1 k8s.io/api/storage/v1alpha1 k8s.io/api/storage/v1beta1 # k8s.io/apiextensions-apiserver v0.0.0-20190508104225-cdabac1ba2af => k8s.io/apiextensions-apiserver v0.0.0-20190315093550-53c4693659ed