Skip to content

Commit 6b1a836

Browse files
Merge pull request openshift#16821 from miminar/image-pruning-dereference-istags
Automatic merge from submit-queue. image-pruning: dereference ImageStreamTags Create strong references to images for each pod/bc/dc/etc that uses `<host>/<repo>:tag` reference. Resolves [bz#1498604](https://bugzilla.redhat.com/show_bug.cgi?id=1498604) and https://bugzilla.redhat.com/show_bug.cgi?id=1386917 Images can manually removed using `oc delete`. Image stream tags having references to these images become obsolete - we may delete them. To be sure that we don't remove reference to image that has just been created (and we don't know about it), make sure to honor `--keep-younger-than`.
2 parents 1bae363 + 1cda0bb commit 6b1a836

File tree

13 files changed

+2232
-1046
lines changed

13 files changed

+2232
-1046
lines changed

pkg/apps/graph/nodes/nodes.go

+86-3
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,69 @@ 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 daemon set 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+
40+
// EnsureDeploymentNode adds the provided upstream deployment to the graph if it does not exist
41+
func EnsureDeploymentNode(g osgraph.MutableUniqueGraph, deployment *kapisext.Deployment) *DeploymentNode {
42+
deploymentName := DeploymentNodeName(deployment)
43+
deploymentNode := osgraph.EnsureUnique(
44+
g,
45+
deploymentName,
46+
func(node osgraph.Node) graph.Node {
47+
return &DeploymentNode{Node: node, Deployment: deployment, IsFound: true}
48+
},
49+
).(*DeploymentNode)
50+
51+
podTemplateSpecNode := kubegraph.EnsurePodTemplateSpecNode(g, &deployment.Spec.Template, deployment.Namespace, deploymentName)
52+
g.AddEdge(deploymentNode, podTemplateSpecNode, osgraph.ContainsEdgeKind)
53+
54+
return deploymentNode
55+
}
56+
57+
func FindOrCreateSyntheticDeploymentNode(g osgraph.MutableUniqueGraph, deployment *kapisext.Deployment) *DeploymentNode {
58+
return osgraph.EnsureUnique(
59+
g,
60+
DeploymentNodeName(deployment),
61+
func(node osgraph.Node) graph.Node {
62+
return &DeploymentNode{Node: node, Deployment: deployment, IsFound: false}
63+
},
64+
).(*DeploymentNode)
65+
}
66+
1167
// EnsureDeploymentConfigNode adds the provided deployment config to the graph if it does not exist
12-
func EnsureDeploymentConfigNode(g osgraph.MutableUniqueGraph, dc *depoyapi.DeploymentConfig) *DeploymentConfigNode {
68+
func EnsureDeploymentConfigNode(g osgraph.MutableUniqueGraph, dc *deployapi.DeploymentConfig) *DeploymentConfigNode {
1369
dcName := DeploymentConfigNodeName(dc)
1470
dcNode := osgraph.EnsureUnique(
1571
g,
@@ -27,7 +83,7 @@ func EnsureDeploymentConfigNode(g osgraph.MutableUniqueGraph, dc *depoyapi.Deplo
2783
return dcNode
2884
}
2985

30-
func FindOrCreateSyntheticDeploymentConfigNode(g osgraph.MutableUniqueGraph, dc *depoyapi.DeploymentConfig) *DeploymentConfigNode {
86+
func FindOrCreateSyntheticDeploymentConfigNode(g osgraph.MutableUniqueGraph, dc *deployapi.DeploymentConfig) *DeploymentConfigNode {
3187
return osgraph.EnsureUnique(
3288
g,
3389
DeploymentConfigNodeName(dc),
@@ -36,3 +92,30 @@ func FindOrCreateSyntheticDeploymentConfigNode(g osgraph.MutableUniqueGraph, dc
3692
},
3793
).(*DeploymentConfigNode)
3894
}
95+
96+
// EnsureReplicaSetNode adds the provided replica set to the graph if it does not exist
97+
func EnsureReplicaSetNode(g osgraph.MutableUniqueGraph, rs *kapisext.ReplicaSet) *ReplicaSetNode {
98+
rsName := ReplicaSetNodeName(rs)
99+
rsNode := osgraph.EnsureUnique(
100+
g,
101+
rsName,
102+
func(node osgraph.Node) graph.Node {
103+
return &ReplicaSetNode{Node: node, ReplicaSet: rs, IsFound: true}
104+
},
105+
).(*ReplicaSetNode)
106+
107+
podTemplateSpecNode := kubegraph.EnsurePodTemplateSpecNode(g, &rs.Spec.Template, rs.Namespace, rsName)
108+
g.AddEdge(rsNode, podTemplateSpecNode, osgraph.ContainsEdgeKind)
109+
110+
return rsNode
111+
}
112+
113+
func FindOrCreateSyntheticReplicaSetNode(g osgraph.MutableUniqueGraph, rs *kapisext.ReplicaSet) *ReplicaSetNode {
114+
return osgraph.EnsureUnique(
115+
g,
116+
ReplicaSetNodeName(rs),
117+
func(node osgraph.Node) graph.Node {
118+
return &ReplicaSetNode{Node: node, ReplicaSet: rs, IsFound: false}
119+
},
120+
).(*ReplicaSetNode)
121+
}

pkg/apps/graph/nodes/types.go

+86
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,73 @@ 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()
14+
DeploymentNodeKind = reflect.TypeOf(kapisext.Deployment{}).Name()
1115
DeploymentConfigNodeKind = reflect.TypeOf(deployapi.DeploymentConfig{}).Name()
16+
ReplicaSetNodeKind = reflect.TypeOf(kapisext.ReplicaSet{}).Name()
1217
)
1318

19+
func DaemonSetNodeName(o *kapisext.DaemonSet) osgraph.UniqueName {
20+
return osgraph.GetUniqueRuntimeObjectNodeName(DaemonSetNodeKind, o)
21+
}
22+
23+
type DaemonSetNode struct {
24+
osgraph.Node
25+
DaemonSet *kapisext.DaemonSet
26+
27+
IsFound bool
28+
}
29+
30+
func (n DaemonSetNode) Found() bool {
31+
return n.IsFound
32+
}
33+
34+
func (n DaemonSetNode) Object() interface{} {
35+
return n.DaemonSet
36+
}
37+
38+
func (n DaemonSetNode) String() string {
39+
return string(DaemonSetNodeName(n.DaemonSet))
40+
}
41+
42+
func (*DaemonSetNode) Kind() string {
43+
return DaemonSetNodeKind
44+
}
45+
46+
func DeploymentNodeName(o *kapisext.Deployment) osgraph.UniqueName {
47+
return osgraph.GetUniqueRuntimeObjectNodeName(DeploymentNodeKind, o)
48+
}
49+
50+
type DeploymentNode struct {
51+
osgraph.Node
52+
Deployment *kapisext.Deployment
53+
54+
IsFound bool
55+
}
56+
57+
func (n DeploymentNode) Found() bool {
58+
return n.IsFound
59+
}
60+
61+
func (n DeploymentNode) Object() interface{} {
62+
return n.Deployment
63+
}
64+
65+
func (n DeploymentNode) String() string {
66+
return string(DeploymentNodeName(n.Deployment))
67+
}
68+
69+
func (*DeploymentNode) Kind() string {
70+
return DeploymentNodeKind
71+
}
72+
1473
func DeploymentConfigNodeName(o *deployapi.DeploymentConfig) osgraph.UniqueName {
1574
return osgraph.GetUniqueRuntimeObjectNodeName(DeploymentConfigNodeKind, o)
1675
}
@@ -37,3 +96,30 @@ func (n DeploymentConfigNode) String() string {
3796
func (*DeploymentConfigNode) Kind() string {
3897
return DeploymentConfigNodeKind
3998
}
99+
100+
func ReplicaSetNodeName(o *kapisext.ReplicaSet) osgraph.UniqueName {
101+
return osgraph.GetUniqueRuntimeObjectNodeName(ReplicaSetNodeKind, o)
102+
}
103+
104+
type ReplicaSetNode struct {
105+
osgraph.Node
106+
ReplicaSet *kapisext.ReplicaSet
107+
108+
IsFound bool
109+
}
110+
111+
func (n ReplicaSetNode) Found() bool {
112+
return n.IsFound
113+
}
114+
115+
func (n ReplicaSetNode) Object() interface{} {
116+
return n.ReplicaSet
117+
}
118+
119+
func (n ReplicaSetNode) String() string {
120+
return string(ReplicaSetNodeName(n.ReplicaSet))
121+
}
122+
123+
func (*ReplicaSetNode) Kind() string {
124+
return ReplicaSetNodeKind
125+
}

pkg/cmd/server/bootstrappolicy/policy.go

+3
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,9 @@ 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(),
555+
rbac.NewRule("get", "list").Groups(extensionsGroup).Resources("deployments").RuleOrDie(),
556+
rbac.NewRule("get", "list").Groups(extensionsGroup).Resources("replicasets").RuleOrDie(),
554557

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

pkg/image/graph/nodes/nodes.go

+6-2
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,12 @@ func EnsureAllImageStreamTagNodes(g osgraph.MutableUniqueGraph, is *imageapi.Ima
3636
return ret
3737
}
3838

39-
func FindImage(g osgraph.MutableUniqueGraph, imageName string) graph.Node {
40-
return g.Find(ImageNodeName(&imageapi.Image{ObjectMeta: metav1.ObjectMeta{Name: imageName}}))
39+
func FindImage(g osgraph.MutableUniqueGraph, imageName string) *ImageNode {
40+
n := g.Find(ImageNodeName(&imageapi.Image{ObjectMeta: metav1.ObjectMeta{Name: imageName}}))
41+
if imageNode, ok := n.(*ImageNode); ok {
42+
return imageNode
43+
}
44+
return nil
4145
}
4246

4347
// EnsureDockerRepositoryNode adds the named Docker repository tag reference to the graph if it does

pkg/image/prune/helper.go

+59
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import (
77
"sort"
88
"strings"
99

10+
kapi "k8s.io/kubernetes/pkg/api"
11+
1012
"github.com/docker/distribution/registry/api/errcode"
1113
"github.com/golang/glog"
1214

@@ -206,3 +208,60 @@ func TryProtocolsWithRegistryURL(registry string, allowInsecure bool, action fun
206208
type retryPath struct{ err error }
207209

208210
func (rp *retryPath) Error() string { return rp.err.Error() }
211+
212+
// ErrBadReference denotes an invalid reference to image, imagestreamtag or imagestreamimage stored in a
213+
// particular object. The object is identified by kind, namespace and name.
214+
type ErrBadReference struct {
215+
kind string
216+
namespace string
217+
name string
218+
targetKind string
219+
reference string
220+
reason string
221+
}
222+
223+
func newErrBadReferenceToImage(reference string, obj *kapi.ObjectReference, reason string) error {
224+
kind := "<UnknownType>"
225+
namespace := ""
226+
name := "<unknown-name>"
227+
if obj != nil {
228+
kind = obj.Kind
229+
namespace = obj.Namespace
230+
name = obj.Name
231+
}
232+
233+
return &ErrBadReference{
234+
kind: kind,
235+
namespace: namespace,
236+
name: name,
237+
reference: reference,
238+
reason: reason,
239+
}
240+
}
241+
242+
func newErrBadReferenceTo(targetKind, reference string, obj *kapi.ObjectReference, reason string) error {
243+
return &ErrBadReference{
244+
kind: obj.Kind,
245+
namespace: obj.Namespace,
246+
name: obj.Name,
247+
targetKind: targetKind,
248+
reference: reference,
249+
reason: reason,
250+
}
251+
}
252+
253+
func (e *ErrBadReference) Error() string {
254+
return e.String()
255+
}
256+
257+
func (e *ErrBadReference) String() string {
258+
name := e.name
259+
if len(e.namespace) > 0 {
260+
name = e.namespace + "/" + name
261+
}
262+
targetKind := "docker image"
263+
if len(e.targetKind) > 0 {
264+
targetKind = e.targetKind
265+
}
266+
return fmt.Sprintf("%s[%s]: invalid %s reference %q: %s", e.kind, name, targetKind, e.reference, e.reason)
267+
}

0 commit comments

Comments
 (0)