@ -27,6 +27,7 @@ import (
batchv1 "k8s.io/api/batch/v1"
corev1 "k8s.io/api/core/v1"
extensionsv1beta1 "k8s.io/api/extensions/v1beta1"
apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
apiextv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
@ -114,6 +115,17 @@ func (w *waiter) waitForResources(created ResourceList) error {
if err := scheme . Scheme . Convert ( v . Object , crd , nil ) ; err != nil {
return false , err
}
if ! w . crdBetaReady ( * crd ) {
return false , nil
}
case * apiextv1 . CustomResourceDefinition :
if err := v . Get ( ) ; err != nil {
return false , err
}
crd := & apiextv1 . CustomResourceDefinition { }
if err := scheme . Scheme . Convert ( v . Object , crd , nil ) ; err != nil {
return false , err
}
if ! w . crdReady ( * crd ) {
return false , nil
}
@ -229,7 +241,10 @@ func (w *waiter) daemonSetReady(ds *appsv1.DaemonSet) bool {
return true
}
func ( w * waiter ) crdReady ( crd apiextv1beta1 . CustomResourceDefinition ) bool {
// Because the v1 extensions API is not available on all supported k8s versions
// yet and because Go doesn't support generics, we need to have a duplicate
// function to support the v1beta1 types
func ( w * waiter ) crdBetaReady ( crd apiextv1beta1 . CustomResourceDefinition ) bool {
for _ , cond := range crd . Status . Conditions {
switch cond . Type {
case apiextv1beta1 . Established :
@ -249,6 +264,26 @@ func (w *waiter) crdReady(crd apiextv1beta1.CustomResourceDefinition) bool {
return false
}
func ( w * waiter ) crdReady ( crd apiextv1 . CustomResourceDefinition ) bool {
for _ , cond := range crd . Status . Conditions {
switch cond . Type {
case apiextv1 . Established :
if cond . Status == apiextv1 . ConditionTrue {
return true
}
case apiextv1 . NamesAccepted :
if cond . Status == apiextv1 . ConditionFalse {
// This indicates a naming conflict, but it's probably not the
// job of this function to fail because of that. Instead,
// we treat it as a success, since the process should be able to
// continue.
return true
}
}
}
return false
}
func ( w * waiter ) statefulSetReady ( sts * appsv1 . StatefulSet ) bool {
// If the update strategy is not a rolling update, there will be nothing to wait for
if sts . Spec . UpdateStrategy . Type != appsv1 . RollingUpdateStatefulSetStrategyType {