Skip to content

Commit 0bfadd2

Browse files
committed
driver/kubernetes: add ownerrefs driver option for owner references
Add support for setting Kubernetes ownerReferences on the builder Deployment/StatefulSet via a new 'ownerrefs' driver option. This allows the builder to be automatically garbage-collected by Kubernetes when its owning resource (e.g. an ephemeral GitHub Actions runner) is deleted. Usage: docker buildx create --driver kubernetes --driver-opt ownerrefs=apiVersion=actions.github.com/v1alpha1,kind=EphemeralRunner,name=runner-xyz,uid=<uid>,controller=true,blockOwnerDeletion=false Multiple owner references can be specified by separating them with semicolons. Each owner reference supports the following fields: apiVersion, kind, name, uid, controller, blockOwnerDeletion closes #2626 Signed-off-by: abhay1999 <abhaychaurasiya19@gmail.com>
1 parent 43fe71e commit 0bfadd2

File tree

3 files changed

+105
-4
lines changed

3 files changed

+105
-4
lines changed

driver/kubernetes/factory.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ import (
1717
"github.com/pkg/errors"
1818
"github.com/sirupsen/logrus"
1919
corev1 "k8s.io/api/core/v1"
20+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
21+
"k8s.io/apimachinery/pkg/types"
2022
"k8s.io/client-go/rest"
2123
)
2224

@@ -272,6 +274,46 @@ func (f *factory) processDriverOpts(deploymentName string, namespace string, cfg
272274

273275
deploymentOpt.Tolerations = append(deploymentOpt.Tolerations, t)
274276
}
277+
case k == "ownerrefs":
278+
refs := strings.Split(v, ";")
279+
deploymentOpt.OwnerReferences = []metav1.OwnerReference{}
280+
for i := range refs {
281+
kvs := strings.Split(refs[i], ",")
282+
283+
ref := metav1.OwnerReference{}
284+
285+
for j := range kvs {
286+
kv := strings.SplitN(kvs[j], "=", 2)
287+
if len(kv) == 2 {
288+
switch kv[0] {
289+
case "apiVersion":
290+
ref.APIVersion = kv[1]
291+
case "kind":
292+
ref.Kind = kv[1]
293+
case "name":
294+
ref.Name = kv[1]
295+
case "uid":
296+
ref.UID = types.UID(kv[1])
297+
case "controller":
298+
b, err := strconv.ParseBool(kv[1])
299+
if err != nil {
300+
return nil, "", "", false, 0, errors.Wrap(err, "invalid ownerrefs controller value")
301+
}
302+
ref.Controller = &b
303+
case "blockOwnerDeletion":
304+
b, err := strconv.ParseBool(kv[1])
305+
if err != nil {
306+
return nil, "", "", false, 0, errors.Wrap(err, "invalid ownerrefs blockOwnerDeletion value")
307+
}
308+
ref.BlockOwnerDeletion = &b
309+
default:
310+
return nil, "", "", false, 0, errors.Errorf("invalid ownerrefs key %q", kv[0])
311+
}
312+
}
313+
}
314+
315+
deploymentOpt.OwnerReferences = append(deploymentOpt.OwnerReferences, ref)
316+
}
275317
case k == "loadbalance":
276318
switch v {
277319
case LoadbalanceSticky, LoadbalanceRandom:

driver/kubernetes/factory_test.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import (
88
"github.com/docker/buildx/driver/bkimage"
99
"github.com/stretchr/testify/require"
1010
v1 "k8s.io/api/core/v1"
11+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
12+
"k8s.io/apimachinery/pkg/types"
1113
"k8s.io/client-go/rest"
1214
)
1315

@@ -267,4 +269,59 @@ func TestFactory_processDriverOpts(t *testing.T) {
267269
require.Error(t, err)
268270
},
269271
)
272+
273+
t.Run(
274+
"OwnerRefs", func(t *testing.T) {
275+
controller := true
276+
blockOwnerDeletion := false
277+
cfg.DriverOpts = map[string]string{
278+
"ownerrefs": "apiVersion=actions.github.com/v1alpha1,kind=EphemeralRunner,name=runner-xyz,uid=b636330d-26b7-417a-8464-c2641438feed,controller=true,blockOwnerDeletion=false",
279+
}
280+
r, _, _, _, _, err := f.processDriverOpts(cfg.Name, "test", cfg)
281+
require.NoError(t, err)
282+
require.Equal(t, []metav1.OwnerReference{
283+
{
284+
APIVersion: "actions.github.com/v1alpha1",
285+
Kind: "EphemeralRunner",
286+
Name: "runner-xyz",
287+
UID: types.UID("b636330d-26b7-417a-8464-c2641438feed"),
288+
Controller: &controller,
289+
BlockOwnerDeletion: &blockOwnerDeletion,
290+
},
291+
}, r.OwnerReferences)
292+
},
293+
)
294+
295+
t.Run(
296+
"MultipleOwnerRefs", func(t *testing.T) {
297+
cfg.DriverOpts = map[string]string{
298+
"ownerrefs": "apiVersion=v1,kind=Pod,name=pod1,uid=uid-1;apiVersion=v1,kind=Pod,name=pod2,uid=uid-2",
299+
}
300+
r, _, _, _, _, err := f.processDriverOpts(cfg.Name, "test", cfg)
301+
require.NoError(t, err)
302+
require.Len(t, r.OwnerReferences, 2)
303+
require.Equal(t, types.UID("uid-1"), r.OwnerReferences[0].UID)
304+
require.Equal(t, types.UID("uid-2"), r.OwnerReferences[1].UID)
305+
},
306+
)
307+
308+
t.Run(
309+
"InvalidOwnerRefKey", func(t *testing.T) {
310+
cfg.DriverOpts = map[string]string{
311+
"ownerrefs": "apiVersion=v1,invalid=foo",
312+
}
313+
_, _, _, _, _, err := f.processDriverOpts(cfg.Name, "test", cfg)
314+
require.Error(t, err)
315+
},
316+
)
317+
318+
t.Run(
319+
"InvalidOwnerRefController", func(t *testing.T) {
320+
cfg.DriverOpts = map[string]string{
321+
"ownerrefs": "apiVersion=v1,controller=notabool",
322+
}
323+
_, _, _, _, _, err := f.processDriverOpts(cfg.Name, "test", cfg)
324+
require.Error(t, err)
325+
},
326+
)
270327
}

driver/kubernetes/manifest/manifest.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ type DeploymentOpt struct {
3838
CustomAnnotations map[string]string
3939
CustomLabels map[string]string
4040
Tolerations []corev1.Toleration
41+
OwnerReferences []metav1.OwnerReference
4142
RequestsCPU string
4243
RequestsMemory string
4344
RequestsEphemeralStorage string
@@ -154,10 +155,11 @@ func NewDeployment(opt *DeploymentOpt) (d *appsv1.Deployment, s *appsv1.Stateful
154155
}
155156

156157
meta := metav1.ObjectMeta{
157-
Namespace: opt.Namespace,
158-
Name: opt.Name,
159-
Labels: labels,
160-
Annotations: annotations,
158+
Namespace: opt.Namespace,
159+
Name: opt.Name,
160+
Labels: labels,
161+
Annotations: annotations,
162+
OwnerReferences: opt.OwnerReferences,
161163
}
162164

163165
for _, cfg := range splitConfigFiles(opt.ConfigFiles) {

0 commit comments

Comments
 (0)