package prune
import (
"fmt"
"time"
kapi "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/client/cache"
deployapi "github.com/openshift/origin/pkg/deploy/api"
deployutil "github.com/openshift/origin/pkg/deploy/util"
)
// DeploymentByDeploymentConfigIndexFunc indexes Deployment items by their associated DeploymentConfig, if none, index with key "orphan"
func DeploymentByDeploymentConfigIndexFunc(obj interface{}) ([]string, error) {
controller, ok := obj.(*kapi.ReplicationController)
if !ok {
return nil, fmt.Errorf("not a replication controller: %v", obj)
}
name := deployutil.DeploymentConfigNameFor(controller)
if len(name) == 0 {
return []string{"orphan"}, nil
}
return []string{controller.Namespace + "/" + name}, nil
}
// Filter filters the set of objects
type Filter interface {
Filter(items []*kapi.ReplicationController) []*kapi.ReplicationController
}
// andFilter ands a set of predicate functions to know if it should be included in the return set
type andFilter struct {
filterPredicates []FilterPredicate
}
// Filter ands the set of predicates evaluated against each item to make a filtered set
func (a *andFilter) Filter(items []*kapi.ReplicationController) []*kapi.ReplicationController {
results := []*kapi.ReplicationController{}
for _, item := range items {
include := true
for _, filterPredicate := range a.filterPredicates {
include = include && filterPredicate(item)
}
if include {
results = append(results, item)
}
}
return results
}
// FilterPredicate is a function that returns true if the object should be included in the filtered set
type FilterPredicate func(item *kapi.ReplicationController) bool
// NewFilterBeforePredicate is a function that returns true if the build was created before the current time minus specified duration
func NewFilterBeforePredicate(d time.Duration) FilterPredicate {
now := unversioned.Now()
before := unversioned.NewTime(now.Time.Add(-1 * d))
return func(item *kapi.ReplicationController) bool {
return item.CreationTimestamp.Before(before)
}
}
// FilterDeploymentsPredicate is a function that returns true if the replication controller is associated with a DeploymentConfig
func FilterDeploymentsPredicate(item *kapi.ReplicationController) bool {
return len(deployutil.DeploymentConfigNameFor(item)) > 0
}
// FilterZeroReplicaSize is a function that returns true if the replication controller size is 0
func FilterZeroReplicaSize(item *kapi.ReplicationController) bool {
return item.Spec.Replicas == 0 && item.Status.Replicas == 0
}
// DataSet provides functions for working with deployment data
type DataSet interface {
GetDeploymentConfig(deployment *kapi.ReplicationController) (*deployapi.DeploymentConfig, bool, error)
ListDeploymentConfigs() ([]*deployapi.DeploymentConfig, error)
ListDeployments() ([]*kapi.ReplicationController, error)
ListDeploymentsByDeploymentConfig(config *deployapi.DeploymentConfig) ([]*kapi.ReplicationController, error)
}
type dataSet struct {
deploymentConfigStore cache.Store
deploymentIndexer cache.Indexer
}
// NewDataSet returns a DataSet over the specified items
func NewDataSet(deploymentConfigs []*deployapi.DeploymentConfig, deployments []*kapi.ReplicationController) DataSet {
deploymentConfigStore := cache.NewStore(cache.MetaNamespaceKeyFunc)
for _, deploymentConfig := range deploymentConfigs {
deploymentConfigStore.Add(deploymentConfig)
}
deploymentIndexer := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{
"deploymentConfig": DeploymentByDeploymentConfigIndexFunc,
})
for _, deployment := range deployments {
deploymentIndexer.Add(deployment)
}
return &dataSet{
deploymentConfigStore: deploymentConfigStore,
deploymentIndexer: deploymentIndexer,
}
}
// GetDeploymentConfig gets the configuration for the given deployment
func (d *dataSet) GetDeploymentConfig(controller *kapi.ReplicationController) (*deployapi.DeploymentConfig, bool, error) {
name := deployutil.DeploymentConfigNameFor(controller)
if len(name) == 0 {
return nil, false, nil
}
var deploymentConfig *deployapi.DeploymentConfig
key := &deployapi.DeploymentConfig{ObjectMeta: kapi.ObjectMeta{Name: name, Namespace: controller.Namespace}}
item, exists, err := d.deploymentConfigStore.Get(key)
if exists {
deploymentConfig = item.(*deployapi.DeploymentConfig)
}
return deploymentConfig, exists, err
}
// ListDeploymentConfigs returns a list of DeploymentConfigs
func (d *dataSet) ListDeploymentConfigs() ([]*deployapi.DeploymentConfig, error) {
results := []*deployapi.DeploymentConfig{}
for _, item := range d.deploymentConfigStore.List() {
results = append(results, item.(*deployapi.DeploymentConfig))
}
return results, nil
}
// ListDeployments returns a list of deployments
func (d *dataSet) ListDeployments() ([]*kapi.ReplicationController, error) {
results := []*kapi.ReplicationController{}
for _, item := range d.deploymentIndexer.List() {
results = append(results, item.(*kapi.ReplicationController))
}
return results, nil
}
// ListDeploymentsByDeploymentConfig returns a list of deployments for the provided configuration
func (d *dataSet) ListDeploymentsByDeploymentConfig(deploymentConfig *deployapi.DeploymentConfig) ([]*kapi.ReplicationController, error) {
results := []*kapi.ReplicationController{}
key := &kapi.ReplicationController{
ObjectMeta: kapi.ObjectMeta{
Namespace: deploymentConfig.Namespace,
Annotations: map[string]string{deployapi.DeploymentConfigAnnotation: deploymentConfig.Name},
},
}
items, err := d.deploymentIndexer.Index("deploymentConfig", key)
if err != nil {
return nil, err
}
for _, item := range items {
results = append(results, item.(*kapi.ReplicationController))
}
return results, nil
}