package util
import (
kapi "k8s.io/kubernetes/pkg/api"
kerrors "k8s.io/kubernetes/pkg/api/errors"
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
"k8s.io/kubernetes/pkg/util/sets"
"github.com/openshift/origin/pkg/project/api"
)
// Associated returns true if the spec.finalizers contains the origin finalizer
func Associated(namespace *kapi.Namespace) bool {
for i := range namespace.Spec.Finalizers {
if api.FinalizerOrigin == namespace.Spec.Finalizers[i] {
return true
}
}
return false
}
// Associate adds the origin finalizer to spec.finalizers if its not there already
func Associate(kubeClient clientset.Interface, namespace *kapi.Namespace) (*kapi.Namespace, error) {
if Associated(namespace) {
return namespace, nil
}
return finalizeInternal(kubeClient, namespace, true)
}
// Finalized returns true if the spec.finalizers does not contain the origin finalizer
func Finalized(namespace *kapi.Namespace) bool {
for i := range namespace.Spec.Finalizers {
if api.FinalizerOrigin == namespace.Spec.Finalizers[i] {
return false
}
}
return true
}
// Finalize will remove the origin finalizer from the namespace
func Finalize(kubeClient clientset.Interface, namespace *kapi.Namespace) (result *kapi.Namespace, err error) {
if Finalized(namespace) {
return namespace, nil
}
// there is a potential for a resource conflict with base kubernetes finalizer
// as a result, we handle resource conflicts in case multiple finalizers try
// to finalize at same time
for {
result, err = finalizeInternal(kubeClient, namespace, false)
if err == nil {
return result, nil
}
if !kerrors.IsConflict(err) {
return nil, err
}
namespace, err = kubeClient.Core().Namespaces().Get(namespace.Name)
if err != nil {
return nil, err
}
}
}
// finalizeInternal will update the namespace finalizer list to either have or not have origin finalizer
func finalizeInternal(kubeClient clientset.Interface, namespace *kapi.Namespace, withOrigin bool) (*kapi.Namespace, error) {
namespaceFinalize := kapi.Namespace{}
namespaceFinalize.ObjectMeta = namespace.ObjectMeta
namespaceFinalize.Spec = namespace.Spec
finalizerSet := sets.NewString()
for i := range namespace.Spec.Finalizers {
finalizerSet.Insert(string(namespace.Spec.Finalizers[i]))
}
if withOrigin {
finalizerSet.Insert(string(api.FinalizerOrigin))
} else {
finalizerSet.Delete(string(api.FinalizerOrigin))
}
namespaceFinalize.Spec.Finalizers = make([]kapi.FinalizerName, 0, len(finalizerSet))
for _, value := range finalizerSet.List() {
namespaceFinalize.Spec.Finalizers = append(namespaceFinalize.Spec.Finalizers, kapi.FinalizerName(value))
}
return kubeClient.Core().Namespaces().Finalize(&namespaceFinalize)
}
// ConvertNamespace transforms a Namespace into a Project
func ConvertNamespace(namespace *kapi.Namespace) *api.Project {
return &api.Project{
ObjectMeta: namespace.ObjectMeta,
Spec: api.ProjectSpec{
Finalizers: namespace.Spec.Finalizers,
},
Status: api.ProjectStatus{
Phase: namespace.Status.Phase,
},
}
}
// convertProject transforms a Project into a Namespace
func ConvertProject(project *api.Project) *kapi.Namespace {
namespace := &kapi.Namespace{
ObjectMeta: project.ObjectMeta,
Spec: kapi.NamespaceSpec{
Finalizers: project.Spec.Finalizers,
},
Status: kapi.NamespaceStatus{
Phase: project.Status.Phase,
},
}
if namespace.Annotations == nil {
namespace.Annotations = map[string]string{}
}
namespace.Annotations[api.ProjectDisplayName] = project.Annotations[api.ProjectDisplayName]
return namespace
}
// ConvertNamespaceList transforms a NamespaceList into a ProjectList
func ConvertNamespaceList(namespaceList *kapi.NamespaceList) *api.ProjectList {
projects := &api.ProjectList{}
for _, n := range namespaceList.Items {
projects.Items = append(projects.Items, *ConvertNamespace(&n))
}
return projects
}