use new upstream deprecations

Signed-off-by: Joe Julian <me@joejulian.name>
pull/8608/head
Joe Julian 5 years ago
parent 160601e784
commit 629579069e
No known key found for this signature in database
GPG Key ID: FAB12BE0575D999B

@ -16,193 +16,64 @@ limitations under the License.
package rules // import "helm.sh/helm/v3/pkg/lint/rules"
import "fmt"
import (
"fmt"
type deprecatedAPI struct {
NewAPI string
DeprecatedIn string
RemovedIn string
}
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apiserver/pkg/endpoints/deprecation"
kscheme "k8s.io/client-go/kubernetes/scheme"
)
// deprecatedAPIs lists APIs that are deprecated (key) with suggested alternatives (value).
var deprecatedAPIs = map[string]deprecatedAPI{
"extensions/v1beta1 Deployment": {
NewAPI: "apps/v1 Deployment",
DeprecatedIn: "v1.9",
RemovedIn: "v1.16",
},
"apps/v1beta1 Deployment": {
NewAPI: "apps/v1 Deployment",
DeprecatedIn: "v1.9",
RemovedIn: "v1.16",
},
"apps/v1beta2 Deployment": {
NewAPI: "apps/v1 Deployment",
DeprecatedIn: "v1.9",
RemovedIn: "v1.16",
},
"apps/v1beta1 StatefulSet": {
NewAPI: "apps/v1 StatefulSet",
DeprecatedIn: "v1.9",
RemovedIn: "v1.16",
},
"apps/v1beta2 StatefulSet": {
NewAPI: "apps/v1 StatefulSet",
DeprecatedIn: "v1.9",
RemovedIn: "v1.16",
},
"extensions/v1beta1 DaemonSet": {
NewAPI: "apps/v1 DaemonSet",
DeprecatedIn: "v1.9",
RemovedIn: "v1.16",
},
"apps/v1beta2 DaemonSet": {
NewAPI: "apps/v1 DaemonSet",
DeprecatedIn: "v1.9",
RemovedIn: "v1.16",
},
"extensions/v1beta1 ReplicaSet": {
NewAPI: "apps/v1 ReplicaSet",
DeprecatedIn: "v1.9",
RemovedIn: "v1.16",
},
"apps/v1beta1 ReplicaSet": {
NewAPI: "apps/v1 ReplicaSet",
DeprecatedIn: "v1.9",
RemovedIn: "v1.16",
},
"apps/v1beta2 ReplicaSet": {
NewAPI: "apps/v1 ReplicaSet",
DeprecatedIn: "v1.9",
RemovedIn: "v1.16",
},
"extensions/v1beta1 NetworkPolicy": {
NewAPI: "networking.k8s.io/v1 NetworkPolicy",
DeprecatedIn: "v1.8",
RemovedIn: "v1.16",
},
"extensions/v1beta1 PodSecurityPolicy": {
NewAPI: "policy/v1beta1 PodSecurityPolicy",
DeprecatedIn: "v1.10",
RemovedIn: "v1.16",
},
"apiextensions.k8s.io/v1beta1 CustomResourceDefinition": {
NewAPI: "apiextensions.k8s.io/v1 CustomResourceDefinition",
DeprecatedIn: "v1.16",
RemovedIn: "v1.19",
},
"extensions/v1beta1 Ingress": {
NewAPI: "networking.k8s.io/v1beta1 Ingress",
DeprecatedIn: "v1.14",
RemovedIn: "v1.22",
},
"rbac.authorization.k8s.io/v1alpha1 ClusterRole": {
NewAPI: "rbac.authorization.k8s.io/v1 ClusterRole",
DeprecatedIn: "v1.17",
RemovedIn: "v1.22",
},
"rbac.authorization.k8s.io/v1alpha1 ClusterRoleList": {
NewAPI: "rbac.authorization.k8s.io/v1 ClusterRoleList",
DeprecatedIn: "v1.17",
RemovedIn: "v1.22",
},
"rbac.authorization.k8s.io/v1alpha1 ClusterRoleBinding": {
NewAPI: "rbac.authorization.k8s.io/v1 ClusterRoleBinding",
DeprecatedIn: "v1.17",
RemovedIn: "v1.22",
},
"rbac.authorization.k8s.io/v1alpha1 ClusterRoleBindingList": {
NewAPI: "rbac.authorization.k8s.io/v1 ClusterRoleBindingList",
DeprecatedIn: "v1.17",
RemovedIn: "v1.22",
},
"rbac.authorization.k8s.io/v1alpha1 Role": {
NewAPI: "rbac.authorization.k8s.io/v1 Role",
DeprecatedIn: "v1.17",
RemovedIn: "v1.22",
},
"rbac.authorization.k8s.io/v1alpha1 RoleList": {
NewAPI: "rbac.authorization.k8s.io/v1 RoleList",
DeprecatedIn: "v1.17",
RemovedIn: "v1.22",
},
"rbac.authorization.k8s.io/v1alpha1 RoleBinding": {
NewAPI: "rbac.authorization.k8s.io/v1 RoleBinding",
DeprecatedIn: "v1.17",
RemovedIn: "v1.22",
},
"rbac.authorization.k8s.io/v1alpha1 RoleBindingList": {
NewAPI: "rbac.authorization.k8s.io/v1 RoleBindingList",
DeprecatedIn: "v1.17",
RemovedIn: "v1.22",
},
"rbac.authorization.k8s.io/v1beta ClusterRole": {
NewAPI: "rbac.authorization.k8s.io/v1 ClusterRole",
DeprecatedIn: "v1.17",
RemovedIn: "v1.22",
},
"rbac.authorization.k8s.io/v1beta1 ClusterRoleList": {
NewAPI: "rbac.authorization.k8s.io/v1 ClusterRoleList",
DeprecatedIn: "v1.17",
RemovedIn: "v1.22",
},
"rbac.authorization.k8s.io/v1beta1 ClusterRoleBinding": {
NewAPI: "rbac.authorization.k8s.io/v1 ClusterRoleBinding",
DeprecatedIn: "v1.17",
RemovedIn: "v1.22",
},
"rbac.authorization.k8s.io/v1beta1 ClusterRoleBindingList": {
NewAPI: "rbac.authorization.k8s.io/v1 ClusterRoleBindingList",
DeprecatedIn: "v1.17",
RemovedIn: "v1.22",
},
"rbac.authorization.k8s.io/v1beta1 Role": {
NewAPI: "rbac.authorization.k8s.io/v1 Role",
DeprecatedIn: "v1.17",
RemovedIn: "v1.22",
},
"rbac.authorization.k8s.io/v1beta1 RoleList": {
NewAPI: "rbac.authorization.k8s.io/v1 RoleList",
DeprecatedIn: "v1.17",
RemovedIn: "v1.22",
},
"rbac.authorization.k8s.io/v1beta1 RoleBinding": {
NewAPI: "rbac.authorization.k8s.io/v1 RoleBinding",
DeprecatedIn: "v1.17",
RemovedIn: "v1.22",
},
"rbac.authorization.k8s.io/v1beta1 RoleBindingList": {
NewAPI: "rbac.authorization.k8s.io/v1 RoleBindingList",
DeprecatedIn: "v1.17",
RemovedIn: "v1.22",
},
}
const (
// This should be set based on the version of client-go being imported
k8sVersionMajor = 1
k8sVersionMinor = 19
)
// deprecatedAPIError indicates than an API is deprecated in Kubernetes
type deprecatedAPIError struct {
Deprecated string
Alternative string
In string
Removed string
Message string
}
func (e deprecatedAPIError) Error() string {
msg := fmt.Sprintf("the kind %q is deprecated as of %q and removed in %q", e.Deprecated, e.In, e.Removed)
if e.Alternative != "" {
msg += fmt.Sprintf(" in favor of %q", e.Alternative)
}
msg := e.Message
return msg
}
func validateNoDeprecations(resource *K8sYamlStruct) error {
// resource is not a resource
if resource.APIVersion == "" {
return nil
}
if resource.Kind == "" {
return nil
}
runtimeObject, err := resourceToRuntimeObject(resource)
if err != nil {
return err
}
if !deprecation.IsDeprecated(runtimeObject, k8sVersionMajor, k8sVersionMinor) {
return nil
}
gvk := fmt.Sprintf("%s %s", resource.APIVersion, resource.Kind)
if dep, ok := deprecatedAPIs[gvk]; ok {
return deprecatedAPIError{
Deprecated: gvk,
Alternative: dep.NewAPI,
In: dep.DeprecatedIn,
Removed: dep.RemovedIn,
Message: deprecation.WarningMessage(runtimeObject),
}
}
func resourceToRuntimeObject(resource *K8sYamlStruct) (runtime.Object, error) {
scheme := runtime.NewScheme()
kscheme.AddToScheme(scheme)
gvk := schema.FromAPIVersionAndKind(resource.APIVersion, resource.Kind)
out, err := scheme.New(gvk)
if err != nil {
return nil, err
}
return nil
out.GetObjectKind().SetGroupVersionKind(gvk)
return out, nil
}

@ -27,10 +27,9 @@ func TestValidateNoDeprecations(t *testing.T) {
if err == nil {
t.Fatal("Expected deprecated extension to be flagged")
}
depErr := err.(deprecatedAPIError)
if depErr.Alternative != "apps/v1 Deployment" {
t.Errorf("Expected %q to be replaced by %q", depErr.Deprecated, depErr.Alternative)
if depErr.Message == "" {
t.Fatal("Expected error message to be non-blank")
}
if err := validateNoDeprecations(&K8sYamlStruct{

Loading…
Cancel
Save