mirror of
https://github.com/notherealmarco/coredns-deployment.git
synced 2025-05-06 04:42:36 +02:00
groundwork (#140)
This commit is contained in:
parent
e6c1d12235
commit
ac020ac1bc
6 changed files with 1082 additions and 0 deletions
231
kubernetes/migration/migrate.go
Normal file
231
kubernetes/migration/migrate.go
Normal file
|
@ -0,0 +1,231 @@
|
|||
package migration
|
||||
// This package provides a set of functions to help handle migrations of CoreDNS Corefiles to be compatible with new
|
||||
// versions of CoreDNS. The task of upgrading CoreDNS is the responsibility of a variety of Kubernetes management tools
|
||||
// (e.g. kubeadm and others), and the precise behavior may be different for each one. This library abstracts some basic
|
||||
// helper functions that make this easier to implement.
|
||||
|
||||
import (
|
||||
"github.com/coredns/deployment/kubernetes/migration/corefile"
|
||||
)
|
||||
|
||||
// Deprecated returns a list of deprecated plugins or directives present in the Corefile. Each Notice returned is a
|
||||
// warning, e.g. "plugin 'foo' is deprecated." An empty list returned means there are no deprecated plugins/options
|
||||
// present in the Corefile.
|
||||
func Deprecated(fromCoreDNSVersion, toCoreDNSVersion, corefileStr string) ([]Notice, error) {
|
||||
return getStatus(fromCoreDNSVersion, toCoreDNSVersion, corefileStr, deprecated)
|
||||
}
|
||||
|
||||
// Removed returns a list of removed plugins or directives present in the Corefile. Each Notice returned is a warning,
|
||||
// e.g. "plugin 'foo' is no longer supported." An empty list returned means there are no removed plugins/options
|
||||
// present in the Corefile.
|
||||
func Removed(fromCoreDNSVersion, toCoreDNSVersion, corefileStr string) ([]Notice, error) {
|
||||
return getStatus(fromCoreDNSVersion, toCoreDNSVersion, corefileStr, removed)
|
||||
}
|
||||
|
||||
// Unsupported returns a list of plugins that are not recognized/supported by the migration tool (but may still be valid in CoreDNS).
|
||||
func Unsupported(fromCoreDNSVersion, toCoreDNSVersion, corefileStr string) ([]Notice, error) {
|
||||
return getStatus(fromCoreDNSVersion, toCoreDNSVersion, corefileStr, unsupported)
|
||||
}
|
||||
|
||||
func getStatus(fromCoreDNSVersion, toCoreDNSVersion, corefileStr, status string) ([]Notice, error) {
|
||||
notices := []Notice{}
|
||||
cf, err := corefile.New(corefileStr)
|
||||
if err != nil {
|
||||
return notices, err
|
||||
}
|
||||
v := fromCoreDNSVersion
|
||||
for {
|
||||
v = Versions[v].nextVersion
|
||||
for _, s := range cf.Servers {
|
||||
for _, p := range s.Plugins {
|
||||
vp, present := Versions[v].plugins[p.Name]
|
||||
if status == unsupported {
|
||||
if present {
|
||||
continue
|
||||
}
|
||||
notices = append(notices, Notice{Plugin: p.Name, Severity: status, Version: v})
|
||||
continue
|
||||
}
|
||||
if !present {
|
||||
continue
|
||||
}
|
||||
if vp.status == status {
|
||||
notices = append(notices, Notice{
|
||||
Plugin: p.Name,
|
||||
Severity: status,
|
||||
Version: v,
|
||||
ReplacedBy: vp.replacedBy,
|
||||
Additional: vp.additional,
|
||||
})
|
||||
continue
|
||||
}
|
||||
for _, o := range p.Options {
|
||||
vo, present := Versions[v].plugins[p.Name].options[o.Name]
|
||||
if status == unsupported {
|
||||
if present {
|
||||
continue
|
||||
}
|
||||
notices = append(notices, Notice{
|
||||
Plugin: p.Name,
|
||||
Option: o.Name,
|
||||
Severity: status,
|
||||
Version: v,
|
||||
ReplacedBy: vo.replacedBy,
|
||||
Additional: vo.additional,
|
||||
})
|
||||
continue
|
||||
}
|
||||
if !present {
|
||||
continue
|
||||
}
|
||||
if vo.status == status {
|
||||
notices = append(notices, Notice{Plugin: p.Name, Option: o.Name, Severity: status, Version: v})
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if v == toCoreDNSVersion {
|
||||
break
|
||||
}
|
||||
}
|
||||
return notices, nil
|
||||
}
|
||||
|
||||
// Migrate returns version of the Corefile migrated to toCoreDNSVersion, or an error if it cannot.
|
||||
func Migrate(fromCoreDNSVersion, toCoreDNSVersion, corefileStr string, deprecations bool) (string, error) {
|
||||
cf, err := corefile.New(corefileStr)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
v := fromCoreDNSVersion
|
||||
for {
|
||||
v = Versions[v].nextVersion
|
||||
newSrvs := []*corefile.Server{}
|
||||
for _, s := range cf.Servers {
|
||||
newPlugs := []*corefile.Plugin{}
|
||||
for _, p := range s.Plugins {
|
||||
vp, present := Versions[v].plugins[p.Name]
|
||||
if !present {
|
||||
newPlugs = append(newPlugs, p)
|
||||
continue
|
||||
}
|
||||
if !deprecations && vp.status == deprecated {
|
||||
newPlugs = append(newPlugs, p)
|
||||
continue
|
||||
}
|
||||
if vp.action != nil {
|
||||
p, err := vp.action(p)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if p == nil {
|
||||
// remove plugin, skip options processing
|
||||
continue
|
||||
}
|
||||
}
|
||||
newOpts := []*corefile.Option{}
|
||||
for _, o := range p.Options {
|
||||
vo, present := Versions[v].plugins[p.Name].options[o.Name]
|
||||
if !present {
|
||||
newOpts = append(newOpts, o)
|
||||
continue
|
||||
}
|
||||
if !deprecations && vo.status == deprecated {
|
||||
newOpts = append(newOpts, o)
|
||||
continue
|
||||
}
|
||||
if vo.action == nil {
|
||||
newOpts = append(newOpts, o)
|
||||
continue
|
||||
}
|
||||
o, err := vo.action(o)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if o == nil {
|
||||
// remove option
|
||||
continue
|
||||
}
|
||||
newOpts = append(newOpts, o)
|
||||
}
|
||||
newPlugs = append(newPlugs,
|
||||
&corefile.Plugin{
|
||||
Name: p.Name,
|
||||
Args: p.Args,
|
||||
Options: newOpts,
|
||||
})
|
||||
}
|
||||
newSrvs = append(newSrvs,
|
||||
&corefile.Server{
|
||||
DomPorts: s.DomPorts,
|
||||
Plugins: newPlugs,
|
||||
},
|
||||
)
|
||||
}
|
||||
cf = corefile.Corefile{Servers: newSrvs}
|
||||
if v == toCoreDNSVersion {
|
||||
break
|
||||
}
|
||||
}
|
||||
return cf.ToString(), nil
|
||||
}
|
||||
|
||||
// Default returns true if the Corefile is the default for a given version of Kubernetes.
|
||||
// Or, if k8sVersion is empty, Default returns true if the Corefile is the default for any version of Kubernetes.
|
||||
func Default(k8sVersion, corefileStr string) bool {
|
||||
cf, err := corefile.New(corefileStr)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
NextVersion:
|
||||
for _, v := range Versions {
|
||||
if k8sVersion != "" && k8sVersion != v.k8sRelease {
|
||||
continue
|
||||
}
|
||||
defCf, err := corefile.New(v.defaultConf)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
// check corefile against k8s release default
|
||||
if len(cf.Servers) != len(defCf.Servers) {
|
||||
continue NextVersion
|
||||
}
|
||||
for _, s := range cf.Servers {
|
||||
defS, found := s.FindMatch(defCf.Servers)
|
||||
if !found {
|
||||
continue NextVersion
|
||||
}
|
||||
if len(s.Plugins) != len(defS.Plugins) {
|
||||
continue NextVersion
|
||||
}
|
||||
for _, p := range s.Plugins {
|
||||
defP, found := p.FindMatch(defS.Plugins)
|
||||
if !found {
|
||||
continue NextVersion
|
||||
}
|
||||
if len(p.Options) != len(defP.Options) {
|
||||
continue NextVersion
|
||||
}
|
||||
for _, o := range p.Options {
|
||||
_, found := o.FindMatch(defP.Options)
|
||||
if !found {
|
||||
continue NextVersion
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Released returns true if dockerImageID matches any released image of CoreDNS.
|
||||
func Released(dockerImageID string) bool {
|
||||
for _, v := range Versions {
|
||||
if v.dockerImageID == dockerImageID {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue