From 57d15c839aa470d339eba91e5b02764ca5135c28 Mon Sep 17 00:00:00 2001 From: David Zhu Date: Fri, 26 Oct 2018 15:28:23 -0700 Subject: [PATCH 1/2] Add Kubernetes CSI Migration Library Dependency --- Gopkg.lock | 16 +- Gopkg.toml | 2 +- .../.gitignore | 2 + .../CONTRIBUTING.md | 31 +++ .../Gopkg.lock | 117 ++++++++++ .../Gopkg.toml | 38 ++++ .../kubernetes-csi-migration-library/LICENSE | 201 ++++++++++++++++++ .../kubernetes-csi-migration-library/OWNERS | 8 + .../README.md | 13 ++ .../RELEASE.md | 9 + .../SECURITY_CONTACTS | 14 ++ .../code-of-conduct.md | 3 + .../plugins/aws_ebs.go | 94 ++++++++ .../plugins/gce_pd.go | 164 ++++++++++++++ .../plugins/in_tree_volume.go | 35 +++ .../translate.go | 97 +++++++++ .../translate_test.go | 77 +++++++ 17 files changed, 918 insertions(+), 3 deletions(-) create mode 100644 vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/.gitignore create mode 100644 vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/CONTRIBUTING.md create mode 100644 vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/Gopkg.lock create mode 100644 vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/Gopkg.toml create mode 100644 vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/LICENSE create mode 100644 vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/OWNERS create mode 100644 vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/README.md create mode 100644 vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/RELEASE.md create mode 100644 vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/SECURITY_CONTACTS create mode 100644 vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/code-of-conduct.md create mode 100644 vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/plugins/aws_ebs.go create mode 100644 vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/plugins/gce_pd.go create mode 100644 vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/plugins/in_tree_volume.go create mode 100644 vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/translate.go create mode 100644 vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/translate_test.go diff --git a/Gopkg.lock b/Gopkg.lock index 0faec1aed3..c983df7b23 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -153,6 +153,17 @@ pruneopts = "" revision = "1bf94ed5c3afa2db7d3117f206f1b00249764790" +[[projects]] + branch = "master" + digest = "1:3162e91e0a20faee7756465f3816ecf389eb3d52850dff8218ca56a1f7060880" + name = "github.com/kubernetes-csi/kubernetes-csi-migration-library" + packages = [ + ".", + "plugins", + ] + pruneopts = "" + revision = "edcf4b4169dcecadd06e071c4801e0373f14d7a2" + [[projects]] digest = "1:76a22f13ffa6d5d0b91beecdcec5c7651a42d3c5fcc12757e578808826fe4b0a" name = "github.com/modern-go/concurrent" @@ -382,8 +393,8 @@ "storage/v1beta1", ] pruneopts = "" - revision = "fd83cbc87e7632ccd8bbab63d2b673d4e0c631cc" - version = "kubernetes-1.12.0" + revision = "357ec6384fa7e10d6ea160d2299a98ddfdc3ab3c" + version = "kubernetes-1.12.1" [[projects]] digest = "1:7aa037a4df5432be2820d164f378d7c22335e5cbba124e90e42114757ebd11ac" @@ -650,6 +661,7 @@ "github.com/golang/mock/gomock", "github.com/golang/protobuf/proto", "github.com/kubernetes-csi/csi-test/driver", + "github.com/kubernetes-csi/kubernetes-csi-migration-library", "google.golang.org/grpc", "google.golang.org/grpc/codes", "google.golang.org/grpc/connectivity", diff --git a/Gopkg.toml b/Gopkg.toml index 16c66e5f80..dca3df0ead 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -26,7 +26,7 @@ [[constraint]] name = "k8s.io/api" - version = "kubernetes-1.12.0" + version = "kubernetes-1.12.1" [[constraint]] name = "k8s.io/apimachinery" diff --git a/vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/.gitignore b/vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/.gitignore new file mode 100644 index 0000000000..566bdf3ab3 --- /dev/null +++ b/vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/.gitignore @@ -0,0 +1,2 @@ +# vim +*.swp diff --git a/vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/CONTRIBUTING.md b/vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/CONTRIBUTING.md new file mode 100644 index 0000000000..de47115137 --- /dev/null +++ b/vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/CONTRIBUTING.md @@ -0,0 +1,31 @@ +# Contributing Guidelines + +Welcome to Kubernetes. We are excited about the prospect of you joining our [community](https://github.com/kubernetes/community)! The Kubernetes community abides by the CNCF [code of conduct](code-of-conduct.md). Here is an excerpt: + +_As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities._ + +## Getting Started + +We have full documentation on how to get started contributing here: + + + +- [Contributor License Agreement](https://git.k8s.io/community/CLA.md) Kubernetes projects require that you sign a Contributor License Agreement (CLA) before we can accept your pull requests +- [Kubernetes Contributor Guide](http://git.k8s.io/community/contributors/guide) - Main contributor documentation, or you can just jump directly to the [contributing section](http://git.k8s.io/community/contributors/guide#contributing) +- [Contributor Cheat Sheet](https://git.k8s.io/community/contributors/guide/contributor-cheatsheet.md) - Common resources for existing developers + +## Mentorship + +- [Mentoring Initiatives](https://git.k8s.io/community/mentoring) - We have a diverse set of mentorship programs available that are always looking for volunteers! + + diff --git a/vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/Gopkg.lock b/vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/Gopkg.lock new file mode 100644 index 0000000000..3cc9dd0823 --- /dev/null +++ b/vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/Gopkg.lock @@ -0,0 +1,117 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + digest = "1:f83d740263b44fdeef3e1bce6147b5d7283fcad1a693d39639be33993ecf3db1" + name = "github.com/gogo/protobuf" + packages = [ + "proto", + "sortkeys", + ] + pruneopts = "UT" + revision = "c0656edd0d9eab7c66d1eb0c568f9039345796f7" + +[[projects]] + digest = "1:2edd2416f89b4e841df0e4a78802ce14d2bc7ad79eba1a45986e39f0f8cb7d87" + name = "github.com/golang/glog" + packages = ["."] + pruneopts = "UT" + revision = "44145f04b68cf362d9c4df2182967c2275eaefed" + +[[projects]] + digest = "1:41bfd4219241b7f7d6e6fdb13fc712576f1337e68e6b895136283b76928fdd66" + name = "github.com/google/gofuzz" + packages = ["."] + pruneopts = "UT" + revision = "44d81051d367757e1c7c6a5a86423ece9afcf63c" + +[[projects]] + digest = "1:51168244381231fe91816c4cd7769902076dcc9c6506aa277bafeb07ea097b74" + name = "golang.org/x/net" + packages = [ + "http2", + "http2/hpack", + "idna", + "lex/httplex", + ] + pruneopts = "UT" + revision = "1c05540f6879653db88113bc4a2b70aec4bd491f" + +[[projects]] + digest = "1:a2ab62866c75542dd18d2b069fec854577a20211d7c0ea6ae746072a1dccdd18" + name = "golang.org/x/text" + packages = [ + "collate", + "collate/build", + "internal/colltab", + "internal/gen", + "internal/tag", + "internal/triegen", + "internal/ucd", + "language", + "secure/bidirule", + "transform", + "unicode/bidi", + "unicode/cldr", + "unicode/norm", + "unicode/rangetable", + ] + pruneopts = "UT" + revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0" + version = "v0.3.0" + +[[projects]] + digest = "1:ef72505cf098abdd34efeea032103377bec06abb61d8a06f002d5d296a4b1185" + name = "gopkg.in/inf.v0" + packages = ["."] + pruneopts = "UT" + revision = "3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4" + version = "v0.9.0" + +[[projects]] + digest = "1:a9cc0da277e05cba6bc1bc058842acee0943a37146d42dc172fd701b1e7c50b3" + name = "k8s.io/api" + packages = ["core/v1"] + pruneopts = "UT" + revision = "357ec6384fa7e10d6ea160d2299a98ddfdc3ab3c" + version = "kubernetes-1.12.1" + +[[projects]] + digest = "1:01926916f6f34e7cc6230e36e66f9690013adcfd32755aebf03ceb91f9c16864" + name = "k8s.io/apimachinery" + packages = [ + "pkg/api/resource", + "pkg/apis/meta/v1", + "pkg/conversion", + "pkg/conversion/queryparams", + "pkg/fields", + "pkg/labels", + "pkg/runtime", + "pkg/runtime/schema", + "pkg/selection", + "pkg/types", + "pkg/util/errors", + "pkg/util/intstr", + "pkg/util/json", + "pkg/util/naming", + "pkg/util/net", + "pkg/util/runtime", + "pkg/util/sets", + "pkg/util/validation", + "pkg/util/validation/field", + "pkg/watch", + "third_party/forked/golang/reflect", + ] + pruneopts = "UT" + revision = "6dd46049f39503a1fc8d65de4bd566829e95faff" + version = "kubernetes-1.12.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + input-imports = [ + "k8s.io/api/core/v1", + "k8s.io/apimachinery/pkg/util/sets", + ] + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/Gopkg.toml b/vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/Gopkg.toml new file mode 100644 index 0000000000..dd3170ca06 --- /dev/null +++ b/vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/Gopkg.toml @@ -0,0 +1,38 @@ +# Gopkg.toml example +# +# Refer to https://golang.github.io/dep/docs/Gopkg.toml.html +# for detailed Gopkg.toml documentation. +# +# required = ["github.com/user/thing/cmd/thing"] +# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] +# +# [[constraint]] +# name = "github.com/user/project" +# version = "1.0.0" +# +# [[constraint]] +# name = "github.com/user/project2" +# branch = "dev" +# source = "github.com/myfork/project2" +# +# [[override]] +# name = "github.com/x/y" +# version = "2.4.0" +# +# [prune] +# non-go = false +# go-tests = true +# unused-packages = true + + +[[constraint]] + name = "k8s.io/api" + version = "kubernetes-1.12.1" + +[[constraint]] + name = "k8s.io/apimachinery" + version = "kubernetes-1.12.0" + +[prune] + go-tests = true + unused-packages = true diff --git a/vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/LICENSE b/vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/LICENSE new file mode 100644 index 0000000000..8dada3edaf --- /dev/null +++ b/vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/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/kubernetes-csi-migration-library/OWNERS b/vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/OWNERS new file mode 100644 index 0000000000..c5df1a2add --- /dev/null +++ b/vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/OWNERS @@ -0,0 +1,8 @@ +# See the OWNERS docs: https://go.k8s.io/owners + +reviewers: + - davidz627 + - saad-ali +approvers: + - davidz627 + - saad-ali diff --git a/vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/README.md b/vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/README.md new file mode 100644 index 0000000000..ff4c954f4d --- /dev/null +++ b/vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/README.md @@ -0,0 +1,13 @@ +# kubernetes-csi-migration-library + +Library of functions to be consumed by various Kubernetes and CSI components in +order to support In-tree plugin to CSI Migration. + +To use, import this library into the component that requires source translation +and use the `TranslateToCSI` and `TranslateToInTree` functions. + +This library has a couple requirements: +1. The driver must have a stable (well-known) driver name +2. The translation library must not assume its running location + 1. This mean's no access to Kubernetes API Server + 2. Assume no network connectivity (no cloud APIs) \ No newline at end of file diff --git a/vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/RELEASE.md b/vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/RELEASE.md new file mode 100644 index 0000000000..7274b344e0 --- /dev/null +++ b/vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/RELEASE.md @@ -0,0 +1,9 @@ +# Release Process + +The Kubernetes Template Project is released on an as-needed basis. The process is as follows: + +1. An issue is proposing a new release with a changelog since the last release +1. All [OWNERS](OWNERS) must LGTM this release +1. An OWNER runs `git tag -s $VERSION` and inserts the changelog and pushes the tag with `git push $VERSION` +1. The release issue is closed +1. An announcement email is sent to `kubernetes-dev@googlegroups.com` with the subject `[ANNOUNCE] kubernetes-template-project $VERSION is released` diff --git a/vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/SECURITY_CONTACTS b/vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/SECURITY_CONTACTS new file mode 100644 index 0000000000..cebd9b48a2 --- /dev/null +++ b/vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/SECURITY_CONTACTS @@ -0,0 +1,14 @@ +# Defined below are the security contacts for this repo. +# +# They are the contact point for the Product Security Team to reach out +# to for triaging and handling of incoming issues. +# +# The below names agree to abide by the +# [Embargo Policy](https://github.com/kubernetes/sig-release/blob/master/security-release-process-documentation/security-release-process.md#embargo-policy) +# and will be removed and replaced if they violate that agreement. +# +# DO NOT REPORT SECURITY VULNERABILITIES DIRECTLY TO THESE NAMES, FOLLOW THE +# INSTRUCTIONS AT https://kubernetes.io/security/ + +davidz627 +saad-ali diff --git a/vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/code-of-conduct.md b/vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/code-of-conduct.md new file mode 100644 index 0000000000..0d15c00cf3 --- /dev/null +++ b/vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/code-of-conduct.md @@ -0,0 +1,3 @@ +# Kubernetes Community Code of Conduct + +Please refer to our [Kubernetes Community Code of Conduct](https://git.k8s.io/community/code-of-conduct.md) diff --git a/vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/plugins/aws_ebs.go b/vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/plugins/aws_ebs.go new file mode 100644 index 0000000000..1b48b57aa2 --- /dev/null +++ b/vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/plugins/aws_ebs.go @@ -0,0 +1,94 @@ +/* +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 plugins + +import ( + "fmt" + "strconv" + + "k8s.io/api/core/v1" +) + +const ( + AWSEBSDriverName = "com.amazon.aws.csi.ebs" + AWSEBSInTreePluginName = "kubernetes.io/aws-ebs" +) + +type AWSEBS struct{} + +// TranslateToCSI takes a volume.Spec and will translate it to a +// CSIPersistentVolumeSource if the translation logic for that +// specific in-tree volume spec has been implemented +func (t *AWSEBS) TranslateInTreePVToCSI(pv *v1.PersistentVolume) (*v1.PersistentVolume, error) { + if pv == nil || pv.Spec.AWSElasticBlockStore == nil { + return nil, fmt.Errorf("pv is nil or AWS EBS not defined on pv") + } + + ebsSource := pv.Spec.AWSElasticBlockStore + + csiSource := &v1.CSIPersistentVolumeSource{ + Driver: AWSEBSDriverName, + VolumeHandle: ebsSource.VolumeID, + ReadOnly: ebsSource.ReadOnly, + FSType: ebsSource.FSType, + VolumeAttributes: map[string]string{ + "partition": strconv.FormatInt(int64(ebsSource.Partition), 10), + }, + } + + pv.Spec.AWSElasticBlockStore = nil + pv.Spec.CSI = csiSource + return pv, nil +} + +// TranslateToIntree takes a CSIPersistentVolumeSource and will translate +// it to a volume.Spec for the specific in-tree volume specified by +//`inTreePlugin`, if that translation logic has been implemented +func (t *AWSEBS) TranslateCSIPVToInTree(pv *v1.PersistentVolume) (*v1.PersistentVolume, error) { + if pv == nil || pv.Spec.CSI == nil { + return nil, fmt.Errorf("pv is nil or CSI source not defined on pv") + } + + csiSource := pv.Spec.CSI + + ebsSource := &v1.AWSElasticBlockStoreVolumeSource{ + VolumeID: csiSource.VolumeHandle, + FSType: csiSource.FSType, + ReadOnly: csiSource.ReadOnly, + } + + if partition, ok := csiSource.VolumeAttributes["partition"]; ok { + partValue, err := strconv.Atoi(partition) + if err != nil { + return nil, fmt.Errorf("Failed to convert partition %v to integer: %v", partition, err) + } + ebsSource.Partition = int32(partValue) + } + + pv.Spec.CSI = nil + pv.Spec.AWSElasticBlockStore = ebsSource + return pv, nil +} + +// CanSupport tests whether the plugin supports a given volume +// specification from the API. The spec pointer should be considered +// const. +func (t *AWSEBS) CanSupport(pv *v1.PersistentVolume) bool { + return pv != nil && pv.Spec.AWSElasticBlockStore != nil +} + +func (t *AWSEBS) GetInTreePluginName() string { + return AWSEBSInTreePluginName +} diff --git a/vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/plugins/gce_pd.go b/vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/plugins/gce_pd.go new file mode 100644 index 0000000000..dcbee9135f --- /dev/null +++ b/vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/plugins/gce_pd.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. +*/ + +package plugins + +import ( + "fmt" + "strconv" + "strings" + + "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/util/sets" +) + +const ( + // GCE PD CSI driver constants + GCEPDDriverName = "com.google.csi.gcepd" + GCEPDInTreePluginName = "kubernetes.io/gce-pd" + + UnspecifiedValue = "UNSPECIFIED" + // Volume ID Expected Format + // "projects/{projectName}/zones/{zoneName}/disks/{diskName}" + volIDZonalFmt = "projects/%s/zones/%s/disks/%s" + // "projects/{projectName}/regions/{regionName}/disks/{diskName}" + volIDRegionalFmt = "projects/%s/regions/%s/disks/%s" + volIDDiskNameValue = 5 + volIDTotalElements = 6 + + // Kubernetes label constants + LabelZoneFailureDomain = "failure-domain.beta.kubernetes.io/zone" + LabelMultiZoneDelimiter = "__" +) + +type GCEPD struct{} + +// TranslateToCSI takes a volume.Spec and will translate it to a +// CSIPersistentVolumeSource if the translation logic for that +// specific in-tree volume spec has been implemented +func (g *GCEPD) TranslateInTreePVToCSI(pv *v1.PersistentVolume) (*v1.PersistentVolume, error) { + var volID string + + if pv == nil || pv.Spec.GCEPersistentDisk == nil { + return nil, fmt.Errorf("pv is nil or GCE Persistent Disk source not defined on pv") + } + + zonesLabel := pv.Labels[LabelZoneFailureDomain] + zones := strings.Split(zonesLabel, LabelMultiZoneDelimiter) + if len(zones) == 1 && len(zones[0]) != 0 { + // Zonal + volID = fmt.Sprintf(volIDZonalFmt, UnspecifiedValue, zones[0], pv.Spec.GCEPersistentDisk.PDName) + } else if len(zones) > 1 { + // Regional + region, err := getRegionFromZones(zones) + if err != nil { + return nil, fmt.Errorf("failed to get region from zones: %v", err) + } + volID = fmt.Sprintf(volIDZonalFmt, UnspecifiedValue, region, pv.Spec.GCEPersistentDisk.PDName) + } else { + // Unspecified + volID = fmt.Sprintf(volIDZonalFmt, UnspecifiedValue, UnspecifiedValue, pv.Spec.GCEPersistentDisk.PDName) + } + + gceSource := pv.Spec.PersistentVolumeSource.GCEPersistentDisk + csiSource := &v1.CSIPersistentVolumeSource{ + Driver: GCEPDDriverName, + VolumeHandle: volID, + ReadOnly: gceSource.ReadOnly, + FSType: gceSource.FSType, + VolumeAttributes: map[string]string{ + "partition": strconv.FormatInt(int64(gceSource.Partition), 10), + }, + } + + pv.Spec.PersistentVolumeSource.GCEPersistentDisk = nil + pv.Spec.PersistentVolumeSource.CSI = csiSource + + return pv, nil +} + +// TranslateToIntree takes a CSIPersistentVolumeSource and will translate +// it to a volume.Spec for the specific in-tree volume specified by +//`inTreePlugin`, if that translation logic has been implemented +func (g *GCEPD) TranslateCSIPVToInTree(pv *v1.PersistentVolume) (*v1.PersistentVolume, error) { + if pv == nil || pv.Spec.CSI == nil { + return nil, fmt.Errorf("pv is nil or CSI source not defined on pv") + } + csiSource := pv.Spec.CSI + + pdName, err := pdNameFromVolumeID(csiSource.VolumeHandle) + if err != nil { + return nil, err + } + + gceSource := &v1.GCEPersistentDiskVolumeSource{ + PDName: pdName, + FSType: csiSource.FSType, + ReadOnly: csiSource.ReadOnly, + } + if partition, ok := csiSource.VolumeAttributes["partition"]; ok { + partInt, err := strconv.Atoi(partition) + if err != nil { + return nil, fmt.Errorf("Failed to convert partition %v to integer: %v", partition, err) + } + gceSource.Partition = int32(partInt) + } + + // TODO: Take the zone/regional information and stick it into the label. + + pv.Spec.CSI = nil + pv.Spec.GCEPersistentDisk = gceSource + + return pv, nil +} + +// CanSupport tests whether the plugin supports a given volume +// specification from the API. The spec pointer should be considered +// const. +func (g *GCEPD) CanSupport(pv *v1.PersistentVolume) bool { + return pv != nil && pv.Spec.GCEPersistentDisk != nil +} + +func (g *GCEPD) GetInTreePluginName() string { + return GCEPDInTreePluginName +} + +func pdNameFromVolumeID(id string) (string, error) { + splitId := strings.Split(id, "/") + if len(splitId) != volIDTotalElements { + return "", fmt.Errorf("failed to get id components. Expected projects/{project}/zones/{zone}/disks/{name}. Got: %s", id) + } + return splitId[volIDDiskNameValue], nil +} + +// TODO: Replace this with the imported one from GCE PD CSI Driver when +// the driver removes all k8s/k8s dependencies +func getRegionFromZones(zones []string) (string, error) { + regions := sets.String{} + if len(zones) < 1 { + return "", fmt.Errorf("no zones specified") + } + for _, zone := range zones { + // Zone expected format {locale}-{region}-{zone} + splitZone := strings.Split(zone, "-") + if len(splitZone) != 3 { + return "", fmt.Errorf("zone in unexpected format, expected: {locale}-{region}-{zone}, got: %v", zone) + } + regions.Insert(strings.Join(splitZone[0:2], "-")) + } + if regions.Len() != 1 { + return "", fmt.Errorf("multiple or no regions gotten from zones, got: %v", regions) + } + return regions.UnsortedList()[0], nil +} diff --git a/vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/plugins/in_tree_volume.go b/vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/plugins/in_tree_volume.go new file mode 100644 index 0000000000..28882d2304 --- /dev/null +++ b/vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/plugins/in_tree_volume.go @@ -0,0 +1,35 @@ +/* +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 plugins + +import "k8s.io/api/core/v1" + +type InTreePlugin interface { + // TranslateToCSI takes a persistent volume and will translate + // the in-tree source to a CSI Source. The input persistent volume can be modified + TranslateInTreePVToCSI(pv *v1.PersistentVolume) (*v1.PersistentVolume, error) + + // TranslateToIntree takes a PV with a CSI PersistentVolume Source and will translate + // it to a in-tree Persistent Volume Source for the in-tree volume + // by the `Driver` field in the CSI Source. The input PV object can be modified + TranslateCSIPVToInTree(pv *v1.PersistentVolume) (*v1.PersistentVolume, error) + + // CanSupport tests whether the plugin supports a given volume + // specification from the API. + CanSupport(pv *v1.PersistentVolume) bool + + // GetInTreePluginName returns the in-tree plugin name this migrates + GetInTreePluginName() string +} diff --git a/vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/translate.go b/vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/translate.go new file mode 100644 index 0000000000..90de606cd3 --- /dev/null +++ b/vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/translate.go @@ -0,0 +1,97 @@ +/* +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 translate + +import ( + "fmt" + + "github.com/kubernetes-csi/kubernetes-csi-migration-library/plugins" + "k8s.io/api/core/v1" +) + +var ( + inTreePlugins = map[string]plugins.InTreePlugin{ + plugins.GCEPDDriverName: &plugins.GCEPD{}, + plugins.AWSEBSDriverName: &plugins.AWSEBS{}, + } +) + +// TranslateToCSI takes a persistent volume and will translate +// the in-tree source to a CSI Source if the translation logic +// has been implemented. The input persistent volume will not +// be modified +func TranslateInTreePVToCSI(pv *v1.PersistentVolume) (*v1.PersistentVolume, error) { + if pv == nil { + return nil, fmt.Errorf("persistent volume was nil") + } + copiedPV := pv.DeepCopy() + for _, curPlugin := range inTreePlugins { + if curPlugin.CanSupport(copiedPV) { + return curPlugin.TranslateInTreePVToCSI(copiedPV) + } + } + return nil, fmt.Errorf("could not find in-tree plugin translation logic for %#v", copiedPV.Name) +} + +// TranslateToIntree takes a PV with a CSI PersistentVolume Source and will translate +// it to a in-tree Persistent Volume Source for the specific in-tree volume specified +// by the `Driver` field in the CSI Source. The input PV object will not be modified. +func TranslateCSIPVToInTree(pv *v1.PersistentVolume) (*v1.PersistentVolume, error) { + if pv == nil || pv.Spec.CSI == nil { + return nil, fmt.Errorf("CSI persistent volume was nil") + } + copiedPV := pv.DeepCopy() + for driverName, curPlugin := range inTreePlugins { + if copiedPV.Spec.CSI.Driver == driverName { + return curPlugin.TranslateCSIPVToInTree(copiedPV) + } + } + return nil, fmt.Errorf("could not find in-tree plugin translation logic for %s", copiedPV.Spec.CSI.Driver) +} + +// IsMigratedByName tests whether there is Migration logic for the in-tree plugin +// for the given `pluginName` +func IsMigratedByName(pluginName string) bool { + for _, curPlugin := range inTreePlugins { + if curPlugin.GetInTreePluginName() == pluginName { + return true + } + } + return false +} + +func GetCSINameFromIntreeName(pluginName string) (string, error) { + for csiDriverName, curPlugin := range inTreePlugins { + if curPlugin.GetInTreePluginName() == pluginName { + return csiDriverName, nil + } + } + return "", fmt.Errorf("Could not find CSI Driver name for plugin %v", pluginName) +} + +// IsPVMigrated tests whether there is Migration logic for the given Persistent Volume +func IsPVMigrated(pv *v1.PersistentVolume) bool { + for _, curPlugin := range inTreePlugins { + if curPlugin.CanSupport(pv) { + return true + } + } + return false +} + +// IsInlineMigrated tests whether there is Migration logic for the given Inline Volume +func IsInlineMigrated(vol *v1.Volume) bool { + return false +} diff --git a/vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/translate_test.go b/vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/translate_test.go new file mode 100644 index 0000000000..41cec89ce1 --- /dev/null +++ b/vendor/github.com/kubernetes-csi/kubernetes-csi-migration-library/translate_test.go @@ -0,0 +1,77 @@ +/* +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 translate + +import ( + "reflect" + "testing" + + "k8s.io/api/core/v1" +) + +func TestTranslationStability(t *testing.T) { + testCases := []struct { + name string + pv *v1.PersistentVolume + }{ + + { + name: "GCE PD PV Source", + pv: &v1.PersistentVolume{ + Spec: v1.PersistentVolumeSpec{ + PersistentVolumeSource: v1.PersistentVolumeSource{ + GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{ + PDName: "test-disk", + FSType: "ext4", + Partition: 0, + ReadOnly: false, + }, + }, + }, + }, + }, + { + name: "AWS EBS PV Source", + pv: &v1.PersistentVolume{ + Spec: v1.PersistentVolumeSpec{ + PersistentVolumeSource: v1.PersistentVolumeSource{ + AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{ + VolumeID: "vol01", + FSType: "ext3", + Partition: 1, + ReadOnly: true, + }, + }, + }, + }, + }, + } + for _, test := range testCases { + t.Logf("Testing %v", test.name) + csiSource, err := TranslateInTreePVToCSI(test.pv) + if err != nil { + t.Errorf("Error when translating to CSI: %v", err) + } + newPV, err := TranslateCSIPVToInTree(csiSource) + if err != nil { + t.Errorf("Error when translating CSI Source to in tree volume: %v", err) + } + if !reflect.DeepEqual(newPV, test.pv) { + t.Errorf("Volumes after translation and back not equal:\n\nOriginal Volume: %#v\n\nRound-trip Volume: %#v", test.pv, newPV) + } + } +} + +// TODO: test for not modifying the original PV. From 57654eb2b2e0a048f90e625544501d0f18cc557b Mon Sep 17 00:00:00 2001 From: David Zhu Date: Fri, 26 Oct 2018 15:28:45 -0700 Subject: [PATCH 2/2] Added migration logic to attach/detach handling and tests --- pkg/controller/csi_handler.go | 49 +++++++++++++++++++------ pkg/controller/csi_handler_test.go | 58 +++++++++++++++++++++++++++++- pkg/controller/util.go | 24 ++++++------- pkg/controller/util_test.go | 4 +-- 4 files changed, 110 insertions(+), 25 deletions(-) diff --git a/pkg/controller/csi_handler.go b/pkg/controller/csi_handler.go index 953087e60c..1c7cf80528 100644 --- a/pkg/controller/csi_handler.go +++ b/pkg/controller/csi_handler.go @@ -34,6 +34,8 @@ import ( csilisters "k8s.io/csi-api/pkg/client/listers/csi/v1alpha1" "github.com/kubernetes-csi/external-attacher/pkg/connection" + + csiMigration "github.com/kubernetes-csi/kubernetes-csi-migration-library" ) // csiHandler is a handler that calls CSI to attach/detach volume. @@ -213,6 +215,22 @@ func (h *csiHandler) hasVAFinalizer(va *storage.VolumeAttachment) bool { return false } +func getCSISource(pv *v1.PersistentVolume) (*v1.CSIPersistentVolumeSource, error) { + if pv == nil { + return nil, fmt.Errorf("could not get CSI source, pv was nil") + } + if pv.Spec.CSI != nil { + return pv.Spec.CSI, nil + } else if csiMigration.IsPVMigrated(pv) { + csiPV, err := csiMigration.TranslateInTreePVToCSI(pv) + if err != nil { + return nil, fmt.Errorf("failed to translate in tree pv to CSI: %v", err) + } + return csiPV.Spec.CSI, nil + } + return nil, fmt.Errorf("pv contained non-csi source that was not migrated") +} + func (h *csiHandler) csiAttach(va *storage.VolumeAttachment) (*storage.VolumeAttachment, map[string]string, error) { glog.V(4).Infof("Starting attach operation for %q", va.Name) // Check as much as possible before adding VA finalizer - it would block @@ -235,20 +253,25 @@ func (h *csiHandler) csiAttach(va *storage.VolumeAttachment) (*storage.VolumeAtt return va, nil, fmt.Errorf("could not add PersistentVolume finalizer: %s", err) } - attributes, err := GetVolumeAttributes(pv) + csiSource, err := getCSISource(pv) if err != nil { return va, nil, err } - volumeHandle, readOnly, err := GetVolumeHandle(pv) + attributes, err := GetVolumeAttributes(csiSource) if err != nil { return va, nil, err } - volumeCapabilities, err := GetVolumeCapabilities(pv) + + volumeHandle, readOnly, err := GetVolumeHandle(csiSource) if err != nil { return va, nil, err } - secrets, err := h.getCredentialsFromPV(pv) + volumeCapabilities, err := GetVolumeCapabilities(pv, csiSource) + if err != nil { + return va, nil, err + } + secrets, err := h.getCredentialsFromPV(csiSource) if err != nil { return va, nil, err } @@ -284,11 +307,17 @@ func (h *csiHandler) csiDetach(va *storage.VolumeAttachment) (*storage.VolumeAtt if err != nil { return va, err } - volumeHandle, _, err := GetVolumeHandle(pv) + + csiSource, err := getCSISource(pv) + if err != nil { + return va, err + } + + volumeHandle, _, err := GetVolumeHandle(csiSource) if err != nil { return va, err } - secrets, err := h.getCredentialsFromPV(pv) + secrets, err := h.getCredentialsFromPV(csiSource) if err != nil { return va, err } @@ -419,11 +448,11 @@ func (h *csiHandler) SyncNewOrUpdatedPersistentVolume(pv *v1.PersistentVolume) { return } -func (h *csiHandler) getCredentialsFromPV(pv *v1.PersistentVolume) (map[string]string, error) { - if pv.Spec.PersistentVolumeSource.CSI == nil { - return nil, fmt.Errorf("persistent volume does not contain CSI volume source") +func (h *csiHandler) getCredentialsFromPV(csiSource *v1.CSIPersistentVolumeSource) (map[string]string, error) { + if csiSource == nil { + return nil, fmt.Errorf("CSI volume source was nil") } - secretRef := pv.Spec.PersistentVolumeSource.CSI.ControllerPublishSecretRef + secretRef := csiSource.ControllerPublishSecretRef if secretRef == nil { return nil, nil } diff --git a/pkg/controller/csi_handler_test.go b/pkg/controller/csi_handler_test.go index 06a1c72a38..1271ef8839 100644 --- a/pkg/controller/csi_handler_test.go +++ b/pkg/controller/csi_handler_test.go @@ -77,6 +77,36 @@ func pv() *v1.PersistentVolume { } } +func gcePDPV() *v1.PersistentVolume { + return &v1.PersistentVolume{ + ObjectMeta: metav1.ObjectMeta{ + Name: testPVName, + Labels: map[string]string{ + "failure-domain.beta.kubernetes.io/zone": "testZone", + }, + }, + Spec: v1.PersistentVolumeSpec{ + PersistentVolumeSource: v1.PersistentVolumeSource{ + GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{ + PDName: "testpd", + FSType: "ext4", + Partition: 0, + ReadOnly: false, + }, + }, + AccessModes: []v1.PersistentVolumeAccessMode{ + v1.ReadWriteOnce, + }, + }, + } +} + +func gcePDPVWithFinalizer() *v1.PersistentVolume { + pv := gcePDPV() + pv.Finalizers = []string{fin} + return pv +} + func pvWithFinalizer() *v1.PersistentVolume { pv := pv() pv.Finalizers = []string{fin} @@ -537,6 +567,20 @@ func TestCSIHandler(t *testing.T) { {"attach", testVolumeHandle, testNodeID, noAttrs, noSecrets, success, notDetached, noMetadata, 0}, }, }, + { + name: "VolumeAttachment with GCEPersistentDiskVolumeSource -> successful attachment", + initialObjects: []runtime.Object{gcePDPVWithFinalizer(), node()}, + addedVA: va(false /*attached*/, "" /*finalizer*/), + expectedActions: []core.Action{ + // Finalizer is saved first + core.NewUpdateAction(vaGroupResourceVersion, metav1.NamespaceNone, va(false /*attached*/, fin)), + core.NewUpdateAction(vaGroupResourceVersion, metav1.NamespaceNone, va(true /*attached*/, fin)), + }, + expectedCSICalls: []csiCall{ + {"attach", "projects/UNSPECIFIED/zones/testZone/disks/testpd", testNodeID, + map[string]string{"partition": "0"}, noSecrets, success, notDetached, noMetadata, 0}, + }, + }, // // DETACH // @@ -713,7 +757,19 @@ func TestCSIHandler(t *testing.T) { {"detach", testVolumeHandle, testNodeID, noAttrs, noSecrets, success, detached, noMetadata, 0}, }, }, - + { + name: "VolumeAttachment with GCEPersistentDiskVolumeSource marked for deletion -> successful detach", + initialObjects: []runtime.Object{gcePDPVWithFinalizer(), node()}, + addedVA: deleted(va(true /*attached*/, fin /*finalizer*/)), + expectedActions: []core.Action{ + // Finalizer is saved first + core.NewUpdateAction(vaGroupResourceVersion, metav1.NamespaceNone, deleted(va(false /*attached*/, ""))), + }, + expectedCSICalls: []csiCall{ + {"detach", "projects/UNSPECIFIED/zones/testZone/disks/testpd", testNodeID, + map[string]string{"partition": "0"}, noSecrets, success, detached, noMetadata, 0}, + }, + }, // // PV finalizers // diff --git a/pkg/controller/util.go b/pkg/controller/util.go index db586d8925..ff5707af95 100644 --- a/pkg/controller/util.go +++ b/pkg/controller/util.go @@ -131,17 +131,17 @@ func GetNodeIDFromNodeInfo(driver string, nodeInfo *csiapi.CSINodeInfo) (string, return "", false } -func GetVolumeCapabilities(pv *v1.PersistentVolume) (*csi.VolumeCapability, error) { +func GetVolumeCapabilities(pv *v1.PersistentVolume, csiSource *v1.CSIPersistentVolumeSource) (*csi.VolumeCapability, error) { m := map[v1.PersistentVolumeAccessMode]bool{} for _, mode := range pv.Spec.AccessModes { m[mode] = true } - if pv.Spec.PersistentVolumeSource.CSI == nil { - return nil, fmt.Errorf("persistent volume does not contain CSI volume source") + if csiSource == nil { + return nil, fmt.Errorf("CSI volume source was nil") } - fsType := pv.Spec.CSI.FSType + fsType := csiSource.FSType if len(fsType) == 0 { fsType = defaultFSType } @@ -180,16 +180,16 @@ func GetVolumeCapabilities(pv *v1.PersistentVolume) (*csi.VolumeCapability, erro return cap, nil } -func GetVolumeHandle(pv *v1.PersistentVolume) (string, bool, error) { - if pv.Spec.PersistentVolumeSource.CSI == nil { - return "", false, fmt.Errorf("persistent volume does not contain CSI volume source") +func GetVolumeHandle(csiSource *v1.CSIPersistentVolumeSource) (string, bool, error) { + if csiSource == nil { + return "", false, fmt.Errorf("csi source was nil") } - return pv.Spec.PersistentVolumeSource.CSI.VolumeHandle, pv.Spec.PersistentVolumeSource.CSI.ReadOnly, nil + return csiSource.VolumeHandle, csiSource.ReadOnly, nil } -func GetVolumeAttributes(pv *v1.PersistentVolume) (map[string]string, error) { - if pv.Spec.PersistentVolumeSource.CSI == nil { - return nil, fmt.Errorf("persistent volume does not contain CSI volume source") +func GetVolumeAttributes(csiSource *v1.CSIPersistentVolumeSource) (map[string]string, error) { + if csiSource == nil { + return nil, fmt.Errorf("csi source was nil") } - return pv.Spec.PersistentVolumeSource.CSI.VolumeAttributes, nil + return csiSource.VolumeAttributes, nil } diff --git a/pkg/controller/util_test.go b/pkg/controller/util_test.go index de2ff7dcc1..79754b7079 100644 --- a/pkg/controller/util_test.go +++ b/pkg/controller/util_test.go @@ -164,7 +164,7 @@ func TestGetVolumeCapabilities(t *testing.T) { }, }, } - cap, err := GetVolumeCapabilities(pv) + cap, err := GetVolumeCapabilities(pv, pv.Spec.CSI) if err == nil && test.expectError { t.Errorf("test %s: expected error, got none", test.name) @@ -272,7 +272,7 @@ func TestGetVolumeHandle(t *testing.T) { } for i, test := range tests { - output, readOnly, err := GetVolumeHandle(test.pv) + output, readOnly, err := GetVolumeHandle(test.pv.Spec.CSI) if output != test.output { t.Errorf("test %d: expected volume ID %q, got %q", i, test.output, output) }