kubeadm: apply deterministic order on certificate phases

The existing logic already creates a proper "tree"
where a CA is always generated before the certs that are signed
by this CA, however the tree is not deterministic.

Always use the default list of certs when generating the
"kubeadm init phase certs" phases. Add a unit test that
makes sure that CA always precede signed certs in the default
lists.

This solves the problem where the help screen for "kubeadm
init" cert sub-phases can have a random order.
This commit is contained in:
Lubomir I. Ivanov 2019-05-31 04:00:41 +03:00
parent 990695c839
commit 2413713c4e
2 changed files with 46 additions and 10 deletions

View File

@ -86,17 +86,19 @@ func newCertSubPhases() []workflow.Phase {
subPhases = append(subPhases, allPhase) subPhases = append(subPhases, allPhase)
certTree, _ := certsphase.GetDefaultCertList().AsMap().CertTree() // This loop assumes that GetDefaultCertList() always returns a list of
// certificate that is preceded by the CAs that sign them.
for ca, certList := range certTree { var lastCACert *certsphase.KubeadmCert
caPhase := newCertSubPhase(ca, runCAPhase(ca)) for _, cert := range certsphase.GetDefaultCertList() {
subPhases = append(subPhases, caPhase) var phase workflow.Phase
if cert.CAName == "" {
for _, cert := range certList { phase = newCertSubPhase(cert, runCAPhase(cert))
certPhase := newCertSubPhase(cert, runCertPhase(cert, ca)) lastCACert = cert
certPhase.LocalFlags = localFlags() } else {
subPhases = append(subPhases, certPhase) phase = newCertSubPhase(cert, runCertPhase(cert, lastCACert))
phase.LocalFlags = localFlags()
} }
subPhases = append(subPhases, phase)
} }
// SA creates the private/public key pair, which doesn't use x509 at all // SA creates the private/public key pair, which doesn't use x509 at all

View File

@ -29,6 +29,40 @@ import (
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
) )
func TestCertListOrder(t *testing.T) {
tests := []struct {
certs Certificates
name string
}{
{
name: "Default Certificate List",
certs: GetDefaultCertList(),
},
{
name: "Cert list less etcd",
certs: GetCertsWithoutEtcd(),
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
var lastCA *KubeadmCert
for i, cert := range test.certs {
if i > 0 && lastCA == nil {
t.Fatalf("CA not present in list before certificate %q", cert.Name)
}
if cert.CAName == "" {
lastCA = cert
} else {
if cert.CAName != lastCA.Name {
t.Fatalf("expected CA name %q, got %q, for certificate %q", lastCA.Name, cert.CAName, cert.Name)
}
}
}
})
}
}
func TestCAPointersValid(t *testing.T) { func TestCAPointersValid(t *testing.T) {
tests := []struct { tests := []struct {
certs Certificates certs Certificates