Skip to content

Commit 3636df4

Browse files
author
Michal Minář
committed
image-pruning: add daemonsets to the graph
Signed-off-by: Michal Minář <[email protected]>
1 parent 2d9691d commit 3636df4

File tree

6 files changed

+128
-6
lines changed

6 files changed

+128
-6
lines changed

pkg/apps/graph/nodes/nodes.go

+32-3
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,42 @@ package nodes
33
import (
44
"github.com/gonum/graph"
55

6+
kapisext "k8s.io/kubernetes/pkg/apis/extensions"
7+
68
osgraph "github.com/openshift/origin/pkg/api/graph"
79
kubegraph "github.com/openshift/origin/pkg/api/kubegraph/nodes"
8-
depoyapi "github.com/openshift/origin/pkg/apps/apis/apps"
10+
deployapi "github.com/openshift/origin/pkg/apps/apis/apps"
911
)
1012

13+
// EnsureDaemonSetNode adds the provided deployment config to the graph if it does not exist
14+
func EnsureDaemonSetNode(g osgraph.MutableUniqueGraph, ds *kapisext.DaemonSet) *DaemonSetNode {
15+
dsName := DaemonSetNodeName(ds)
16+
dsNode := osgraph.EnsureUnique(
17+
g,
18+
dsName,
19+
func(node osgraph.Node) graph.Node {
20+
return &DaemonSetNode{Node: node, DaemonSet: ds, IsFound: true}
21+
},
22+
).(*DaemonSetNode)
23+
24+
podTemplateSpecNode := kubegraph.EnsurePodTemplateSpecNode(g, &ds.Spec.Template, ds.Namespace, dsName)
25+
g.AddEdge(dsNode, podTemplateSpecNode, osgraph.ContainsEdgeKind)
26+
27+
return dsNode
28+
}
29+
30+
func FindOrCreateSyntheticDaemonSetNode(g osgraph.MutableUniqueGraph, ds *kapisext.DaemonSet) *DaemonSetNode {
31+
return osgraph.EnsureUnique(
32+
g,
33+
DaemonSetNodeName(ds),
34+
func(node osgraph.Node) graph.Node {
35+
return &DaemonSetNode{Node: node, DaemonSet: ds, IsFound: false}
36+
},
37+
).(*DaemonSetNode)
38+
}
39+
1140
// EnsureDeploymentConfigNode adds the provided deployment config to the graph if it does not exist
12-
func EnsureDeploymentConfigNode(g osgraph.MutableUniqueGraph, dc *depoyapi.DeploymentConfig) *DeploymentConfigNode {
41+
func EnsureDeploymentConfigNode(g osgraph.MutableUniqueGraph, dc *deployapi.DeploymentConfig) *DeploymentConfigNode {
1342
dcName := DeploymentConfigNodeName(dc)
1443
dcNode := osgraph.EnsureUnique(
1544
g,
@@ -27,7 +56,7 @@ func EnsureDeploymentConfigNode(g osgraph.MutableUniqueGraph, dc *depoyapi.Deplo
2756
return dcNode
2857
}
2958

30-
func FindOrCreateSyntheticDeploymentConfigNode(g osgraph.MutableUniqueGraph, dc *depoyapi.DeploymentConfig) *DeploymentConfigNode {
59+
func FindOrCreateSyntheticDeploymentConfigNode(g osgraph.MutableUniqueGraph, dc *deployapi.DeploymentConfig) *DeploymentConfigNode {
3160
return osgraph.EnsureUnique(
3261
g,
3362
DeploymentConfigNodeName(dc),

pkg/apps/graph/nodes/types.go

+30
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,44 @@ package nodes
33
import (
44
"reflect"
55

6+
kapisext "k8s.io/kubernetes/pkg/apis/extensions"
7+
68
osgraph "github.com/openshift/origin/pkg/api/graph"
79
deployapi "github.com/openshift/origin/pkg/apps/apis/apps"
810
)
911

1012
var (
13+
DaemonSetNodeKind = reflect.TypeOf(kapisext.DaemonSet{}).Name()
1114
DeploymentConfigNodeKind = reflect.TypeOf(deployapi.DeploymentConfig{}).Name()
1215
)
1316

17+
func DaemonSetNodeName(o *kapisext.DaemonSet) osgraph.UniqueName {
18+
return osgraph.GetUniqueRuntimeObjectNodeName(DaemonSetNodeKind, o)
19+
}
20+
21+
type DaemonSetNode struct {
22+
osgraph.Node
23+
DaemonSet *kapisext.DaemonSet
24+
25+
IsFound bool
26+
}
27+
28+
func (n DaemonSetNode) Found() bool {
29+
return n.IsFound
30+
}
31+
32+
func (n DaemonSetNode) Object() interface{} {
33+
return n.DaemonSet
34+
}
35+
36+
func (n DaemonSetNode) String() string {
37+
return string(DaemonSetNodeName(n.DaemonSet))
38+
}
39+
40+
func (*DaemonSetNode) Kind() string {
41+
return DaemonSetNodeKind
42+
}
43+
1444
func DeploymentConfigNodeName(o *deployapi.DeploymentConfig) osgraph.UniqueName {
1545
return osgraph.GetUniqueRuntimeObjectNodeName(DeploymentConfigNodeKind, o)
1646
}

pkg/cmd/server/bootstrappolicy/policy.go

+1
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,7 @@ func GetOpenshiftBootstrapClusterRoles() []rbac.ClusterRole {
551551
rbac.NewRule("list").Groups(kapiGroup).Resources("limitranges").RuleOrDie(),
552552
rbac.NewRule("get", "list").Groups(buildGroup, legacyBuildGroup).Resources("buildconfigs", "builds").RuleOrDie(),
553553
rbac.NewRule("get", "list").Groups(deployGroup, legacyDeployGroup).Resources("deploymentconfigs").RuleOrDie(),
554+
rbac.NewRule("get", "list").Groups(extensionsGroup).Resources("daemonsets").RuleOrDie(),
554555

555556
rbac.NewRule("delete").Groups(imageGroup, legacyImageGroup).Resources("images").RuleOrDie(),
556557
rbac.NewRule("get", "list").Groups(imageGroup, legacyImageGroup).Resources("images", "imagestreams").RuleOrDie(),

pkg/image/prune/prune.go

+20-3
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
kerrors "k8s.io/apimachinery/pkg/util/errors"
2222
"k8s.io/apimachinery/pkg/util/sets"
2323
kapi "k8s.io/kubernetes/pkg/api"
24+
kapisext "k8s.io/kubernetes/pkg/apis/extensions"
2425
"k8s.io/kubernetes/pkg/client/retry"
2526

2627
"github.com/openshift/origin/pkg/api/graph"
@@ -134,8 +135,9 @@ type PrunerOptions struct {
134135
BCs *buildapi.BuildConfigList
135136
// Builds is the entire list of builds across all namespaces in the cluster.
136137
Builds *buildapi.BuildList
137-
// DCs is the entire list of deployment configs across all namespaces in the
138-
// cluster.
138+
// DSs is the entire list of daemon sets across all namespaces in the cluster.
139+
DSs *kapisext.DaemonSetList
140+
// DCs is the entire list of deployment configs across all namespaces in the cluster.
139141
DCs *deployapi.DeploymentConfigList
140142
// LimitRanges is a map of LimitRanges across namespaces, being keys in this map.
141143
LimitRanges map[string][]*kapi.LimitRange
@@ -183,7 +185,7 @@ var _ Pruner = &pruner{}
183185
// defined in their namespace will be considered for pruning. Important to note is
184186
// the fact that this flag does not work in any combination with the keep* flags.
185187
//
186-
// images, streams, pods, rcs, bcs, builds, and dcs are the resources used to run
188+
// images, streams, pods, rcs, bcs, builds, daemonsets and dcs are the resources used to run
187189
// the pruning algorithm. These should be the full list for each type from the
188190
// cluster; otherwise, the pruning algorithm might result in incorrect
189191
// calculations and premature pruning.
@@ -198,6 +200,7 @@ var _ Pruner = &pruner{}
198200
// - any running pods
199201
// - any pending pods
200202
// - any replication controllers
203+
// - any daemonsets
201204
// - any deployment configs
202205
// - any build configs
203206
// - any builds
@@ -242,6 +245,7 @@ func NewPruner(options PrunerOptions) (Pruner, error) {
242245
if err := addBuildsToGraph(g, options.Builds); err != nil {
243246
return nil, err
244247
}
248+
addDaemonSetsToGraph(g, options.DSs)
245249
addDeploymentConfigsToGraph(g, options.DCs)
246250

247251
return &pruner{
@@ -472,6 +476,19 @@ func addReplicationControllersToGraph(g graph.Graph, rcs *kapi.ReplicationContro
472476
}
473477
}
474478

479+
// addDaemonSetsToGraph adds daemon set to the graph.
480+
//
481+
// Edges are added to the graph from each daemon set to the images specified by its pod spec's list of
482+
// containers, as long as the image is managed by OpenShift.
483+
func addDaemonSetsToGraph(g graph.Graph, dss *kapisext.DaemonSetList) {
484+
for i := range dss.Items {
485+
ds := &dss.Items[i]
486+
glog.V(4).Infof("Examining DaemonSet %s", getName(ds))
487+
dsNode := deploygraph.EnsureDaemonSetNode(g, ds)
488+
addPodSpecToGraph(g, &ds.Spec.Template.Spec, dsNode)
489+
}
490+
}
491+
475492
// addDeploymentConfigsToGraph adds deployment configs to the graph.
476493
//
477494
// Edges are added to the graph from each deployment config to the images

pkg/image/prune/prune_test.go

+35
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"k8s.io/client-go/rest/fake"
2222
clientgotesting "k8s.io/client-go/testing"
2323
kapi "k8s.io/kubernetes/pkg/api"
24+
kapisext "k8s.io/kubernetes/pkg/apis/extensions"
2425
"k8s.io/kubernetes/staging/src/k8s.io/apimachinery/pkg/util/diff"
2526

2627
"github.com/openshift/origin/pkg/api/graph"
@@ -244,6 +245,26 @@ func rc(namespace, name string, containerImages ...string) kapi.ReplicationContr
244245
}
245246
}
246247

248+
func dsList(dss ...kapisext.DaemonSet) kapisext.DaemonSetList {
249+
return kapisext.DaemonSetList{
250+
Items: dss,
251+
}
252+
}
253+
254+
func ds(namespace, name string, containerImages ...string) kapisext.DaemonSet {
255+
return kapisext.DaemonSet{
256+
ObjectMeta: metav1.ObjectMeta{
257+
Namespace: namespace,
258+
Name: name,
259+
},
260+
Spec: kapisext.DaemonSetSpec{
261+
Template: kapi.PodTemplateSpec{
262+
Spec: podSpec(containerImages...),
263+
},
264+
},
265+
}
266+
}
267+
247268
func dcList(dcs ...deployapi.DeploymentConfig) deployapi.DeploymentConfigList {
248269
return deployapi.DeploymentConfigList{
249270
Items: dcs,
@@ -479,6 +500,7 @@ func TestImagePruning(t *testing.T) {
479500
rcs kapi.ReplicationControllerList
480501
bcs buildapi.BuildConfigList
481502
builds buildapi.BuildList
503+
dss kapisext.DaemonSetList
482504
dcs deployapi.DeploymentConfigList
483505
limits map[string][]*kapi.LimitRange
484506
expectedImageDeletions []string
@@ -634,6 +656,15 @@ func TestImagePruning(t *testing.T) {
634656
expectedImageDeletions: []string{},
635657
},
636658

659+
"referenced by daemonset - don't prune": {
660+
images: imageList(
661+
image("sha256:0000000000000000000000000000000000000000000000000000000000000000", registryHost+"/foo/bar@sha256:0000000000000000000000000000000000000000000000000000000000000000"),
662+
image("sha256:0000000000000000000000000000000000000000000000000000000000000001", registryHost+"/foo/bar@sha256:0000000000000000000000000000000000000000000000000000000000000001"),
663+
),
664+
dss: dsList(ds("foo", "rc1", registryHost+"/foo/bar@sha256:0000000000000000000000000000000000000000000000000000000000000000")),
665+
expectedImageDeletions: []string{"sha256:0000000000000000000000000000000000000000000000000000000000000001"},
666+
},
667+
637668
"referenced by bc - sti - ImageStreamImage - don't prune": {
638669
images: imageList(image("sha256:0000000000000000000000000000000000000000000000000000000000000000", registryHost+"/foo/bar@sha256:0000000000000000000000000000000000000000000000000000000000000000")),
639670
bcs: bcList(bc("foo", "bc1", "source", "ImageStreamImage", "foo", "bar@sha256:0000000000000000000000000000000000000000000000000000000000000000")),
@@ -1143,6 +1174,7 @@ func TestImagePruning(t *testing.T) {
11431174
RCs: &test.rcs,
11441175
BCs: &test.bcs,
11451176
Builds: &test.builds,
1177+
DSs: &test.dss,
11461178
DCs: &test.dcs,
11471179
LimitRanges: test.limits,
11481180
RegistryURL: &url.URL{Scheme: "https", Host: registryHost},
@@ -1389,6 +1421,7 @@ func TestRegistryPruning(t *testing.T) {
13891421
RCs: &kapi.ReplicationControllerList{},
13901422
BCs: &buildapi.BuildConfigList{},
13911423
Builds: &buildapi.BuildList{},
1424+
DSs: &kapisext.DaemonSetList{},
13921425
DCs: &deployapi.DeploymentConfigList{},
13931426
RegistryURL: &url.URL{Scheme: "https", Host: "registry1.io"},
13941427
}
@@ -1447,6 +1480,7 @@ func TestImageWithStrongAndWeakRefsIsNotPruned(t *testing.T) {
14471480
rcs := rcList()
14481481
bcs := bcList()
14491482
builds := buildList()
1483+
dss := dsList()
14501484
dcs := dcList()
14511485

14521486
options := PrunerOptions{
@@ -1456,6 +1490,7 @@ func TestImageWithStrongAndWeakRefsIsNotPruned(t *testing.T) {
14561490
RCs: &rcs,
14571491
BCs: &bcs,
14581492
Builds: &builds,
1493+
DSs: &dss,
14591494
DCs: &dcs,
14601495
}
14611496
keepYoungerThan := 24 * time.Hour

pkg/oc/admin/prune/images.go

+10
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"time"
1616

1717
"github.com/spf13/cobra"
18+
kerrors "k8s.io/apimachinery/pkg/api/errors"
1819
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1920
knet "k8s.io/apimachinery/pkg/util/net"
2021
restclient "k8s.io/client-go/rest"
@@ -261,6 +262,14 @@ func (o PruneImagesOptions) Run() error {
261262
return err
262263
}
263264

265+
allDSs, err := o.KubeClient.Extensions().DaemonSets(o.Namespace).List(metav1.ListOptions{})
266+
if err != nil {
267+
if !kerrors.IsForbidden(err) {
268+
return err
269+
}
270+
fmt.Fprintf(os.Stderr, "Failed to list daemonsets: %v\n - * Make sure to update clusterRoleBindings.\n", err)
271+
}
272+
264273
allDCs, err := o.AppsClient.DeploymentConfigs(o.Namespace).List(metav1.ListOptions{})
265274
if err != nil {
266275
return err
@@ -332,6 +341,7 @@ func (o PruneImagesOptions) Run() error {
332341
RCs: allRCs,
333342
BCs: allBCs,
334343
Builds: allBuilds,
344+
DSs: allDSs,
335345
DCs: allDCs,
336346
LimitRanges: limitRangesMap,
337347
DryRun: o.Confirm == false,

0 commit comments

Comments
 (0)