Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: [TKC-2895] pvc config #6074

Merged
merged 37 commits into from
Dec 19, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
7530e05
feat: pvc config
vsukhin Dec 11, 2024
6d67658
fix: rename var
vsukhin Dec 11, 2024
76ea394
fix: dep update
vsukhin Dec 11, 2024
6b99bc4
fix: map pvc to api
vsukhin Dec 11, 2024
a7c36c0
fix: map to kube
vsukhin Dec 11, 2024
8e8d073
fix: add pvc to control plane
vsukhin Dec 11, 2024
3bbba25
cleanup pvcs
vsukhin Dec 12, 2024
d9fcff8
fix: merge pvcs map
vsukhin Dec 12, 2024
bd2cf57
fix: add pvcs to service spec
vsukhin Dec 12, 2024
0d02d16
fix: remove duplication
vsukhin Dec 12, 2024
b85e274
fix: dep update
vsukhin Dec 12, 2024
fd2dd60
fix: setvice pvcs
vsukhin Dec 12, 2024
551f1b2
fi: dep update
vsukhin Dec 12, 2024
6faffdb
fix: append pvcs
vsukhin Dec 12, 2024
da9e7f1
fix: copy service pvcs
vsukhin Dec 12, 2024
5417211
fix: pvc name for execution
vsukhin Dec 12, 2024
597a69a
fix: register pvc names
vsukhin Dec 12, 2024
bd3aad2
fix: convert pvc
vsukhin Dec 13, 2024
95c8992
fix: move fields to boxed strings
vsukhin Dec 13, 2024
54b352d
fix: dep update
vsukhin Dec 13, 2024
c83e10b
Merge branch 'main' into vsukhin/feature/test-workflow-pvcs
vsukhin Dec 13, 2024
3520a1a
fix: pass pvc names
vsukhin Dec 16, 2024
6effa79
fix: renname cobfig field
vsukhin Dec 16, 2024
f89592e
fix: remove var
vsukhin Dec 16, 2024
c47ff99
fix: add new pvc config fields
vsukhin Dec 16, 2024
f2dd57b
fix: pvc mapping
vsukhin Dec 17, 2024
a6f70f4
fix: json tag
vsukhin Dec 17, 2024
bc49ed2
fix: use proper pvc name
vsukhin Dec 18, 2024
ea3e45c
fix: merge maps
vsukhin Dec 18, 2024
691a5e9
fix: api spec format
vsukhin Dec 18, 2024
19fadbf
fix: typo
vsukhin Dec 18, 2024
f242e45
fix: format methods
vsukhin Dec 18, 2024
978e7aa
fix: use map instead of slice
vsukhin Dec 18, 2024
1ae2d0a
fix: rename method
vsukhin Dec 18, 2024
9de4313
fix: unique ref
vsukhin Dec 18, 2024
2ecd423
fix: use root id
vsukhin Dec 18, 2024
6c46caa
fix: dep update
vsukhin Dec 19, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions api/v1/testkube.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8797,6 +8797,10 @@ components:
$ref: "#/components/schemas/TestWorkflowEvent"
execution:
$ref: "#/components/schemas/TestWorkflowTagSchema"
pvcs:
type: object
additionalProperties:
$ref: "#/components/schemas/TestWorkflowPvcConfig"

TestWorkflowTemplateSpec:
type: object
Expand Down Expand Up @@ -8835,6 +8839,10 @@ components:
$ref: "#/components/schemas/TestWorkflowEvent"
execution:
$ref: "#/components/schemas/TestWorkflowTagSchema"
pvcs:
type: object
additionalProperties:
$ref: "#/components/schemas/TestWorkflowPvcConfig"

TestWorkflowStepControl:
type: object
Expand Down Expand Up @@ -10588,6 +10596,31 @@ components:
must be defined
type: boolean

TestWorkflowPvcConfig:
type: object
properties:
shared:
description: Specify whether the pvc should be shared between test workflow pods
type: boolean
accessModes:
description: 'Access mode for claim storage. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes/#access-modes'
type: array
items:
type: string
volumeMode:
description: 'Volume mode indicates the consumption of the volume as either a filesystem or block device.
More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes/#volume-mode'
type: string
resources:
description: 'Resources required for pvc'
$ref: "#/components/schemas/TestWorkflowResources"
storageClassName:
description: 'Storage class name specifies the name of a StorageClass. More info: https://kubernetes.io/docs/concepts/storage/storage-classes/'
type: string
selector:
description: Only the volumes whose labels match the selector can be bound to the claim
$ref: "#/components/schemas/LabelSelector"

#
# Errors
#
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ require (
github.com/keygen-sh/jsonapi-go v1.2.1
github.com/keygen-sh/keygen-go/v3 v3.2.0
github.com/kubepug/kubepug v1.7.1
github.com/kubeshop/testkube-operator v1.17.55-0.20241118133003-70462ac10f4a
github.com/kubeshop/testkube-operator v1.17.55-0.20241211150637-26f07cccd389
github.com/minio/minio-go/v7 v7.0.66
github.com/montanaflynn/stats v0.7.1
github.com/moogar0880/problems v0.1.1
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -336,8 +336,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kubepug/kubepug v1.7.1 h1:LKhfSxS8Y5mXs50v+3Lpyec+cogErDLcV7CMUuiaisw=
github.com/kubepug/kubepug v1.7.1/go.mod h1:lv+HxD0oTFL7ZWjj0u6HKhMbbTIId3eG7aWIW0gyF8g=
github.com/kubeshop/testkube-operator v1.17.55-0.20241118133003-70462ac10f4a h1:xget2cwwqOL+K2Op9FPbMgfzj9lSVJAzZ9p48yxuFrE=
github.com/kubeshop/testkube-operator v1.17.55-0.20241118133003-70462ac10f4a/go.mod h1:P47tw1nKQFufdsZndyq2HG2MSa0zK/lU0XpRfZtEmIk=
github.com/kubeshop/testkube-operator v1.17.55-0.20241211150637-26f07cccd389 h1:dP8c/kJmIFzy6F07qG+Wmo3jq8dfEvjYcAItJHDyjJQ=
github.com/kubeshop/testkube-operator v1.17.55-0.20241211150637-26f07cccd389/go.mod h1:P47tw1nKQFufdsZndyq2HG2MSa0zK/lU0XpRfZtEmIk=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/lithammer/fuzzysearch v1.1.8 h1:/HIuJnjHuXS8bKaiTMeeDlW2/AyIWk2brx1V8LFgLN4=
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,5 @@ type TestWorkflowIndependentStepParallel struct {
After []TestWorkflowIndependentStep `json:"after,omitempty"`
Events []TestWorkflowEvent `json:"events,omitempty"`
Execution *TestWorkflowTagSchema `json:"execution,omitempty"`
Pvcs map[string]TestWorkflowPvcConfig `json:"pvcs,omitempty"`
}
23 changes: 23 additions & 0 deletions pkg/api/v1/testkube/model_test_workflow_pvc_config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Testkube API
*
* Testkube provides a Kubernetes-native framework for test definition, execution and results
*
* API version: 1.0.0
* Contact: testkube@kubeshop.io
* Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git)
*/
package testkube

type TestWorkflowPvcConfig struct {
// Specify whether the pvc should be shared between test workflow pods
Shared bool `json:"shared,omitempty"`
// Access mode for claim storage. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes/#access-modes
AccessModes []string `json:"accessModes,omitempty"`
// Volume mode indicates the consumption of the volume as either a filesystem or block device. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes/#volume-mode
VolumeMode string `json:"volumeMode,omitempty"`
Resources *TestWorkflowResources `json:"resources,omitempty"`
// Storage class name specifies the name of a StorageClass. More info: https://kubernetes.io/docs/concepts/storage/storage-classes/
StorageClassName string `json:"storageClassName,omitempty"`
Selector *LabelSelector `json:"selector,omitempty"`
}
1 change: 1 addition & 0 deletions pkg/api/v1/testkube/model_test_workflow_spec.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@ type TestWorkflowSpec struct {
After []TestWorkflowStep `json:"after,omitempty"`
Events []TestWorkflowEvent `json:"events,omitempty"`
Execution *TestWorkflowTagSchema `json:"execution,omitempty"`
Pvcs map[string]TestWorkflowPvcConfig `json:"pvcs,omitempty"`
}
1 change: 1 addition & 0 deletions pkg/api/v1/testkube/model_test_workflow_step_parallel.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,5 @@ type TestWorkflowStepParallel struct {
After []TestWorkflowStep `json:"after,omitempty"`
Events []TestWorkflowEvent `json:"events,omitempty"`
Execution *TestWorkflowTagSchema `json:"execution,omitempty"`
Pvcs map[string]TestWorkflowPvcConfig `json:"pvcs,omitempty"`
}
1 change: 1 addition & 0 deletions pkg/api/v1/testkube/model_test_workflow_template_spec.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,5 @@ type TestWorkflowTemplateSpec struct {
After []TestWorkflowIndependentStep `json:"after,omitempty"`
Events []TestWorkflowEvent `json:"events,omitempty"`
Execution *TestWorkflowTagSchema `json:"execution,omitempty"`
Pvcs map[string]TestWorkflowPvcConfig `json:"pvcs,omitempty"`
}
15 changes: 15 additions & 0 deletions pkg/mapper/testworkflows/kube_openapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -915,6 +915,7 @@ func MapStepParallelKubeToAPI(v testworkflowsv1.StepParallel) testkube.TestWorkf
Run: common.MapPtr(v.Run, MapStepRunKubeToAPI),
Execute: common.MapPtr(v.Execute, MapStepExecuteKubeToAPI),
Artifacts: common.MapPtr(v.Artifacts, MapStepArtifactsKubeToAPI),
Pvcs: common.MapMap(v.Pvcs, MapPvcConfigKubeToAPI),
}
}

Expand Down Expand Up @@ -948,6 +949,7 @@ func MapIndependentStepParallelKubeToAPI(v testworkflowsv1.IndependentStepParall
Run: common.MapPtr(v.Run, MapStepRunKubeToAPI),
Execute: common.MapPtr(v.Execute, MapStepExecuteKubeToAPI),
Artifacts: common.MapPtr(v.Artifacts, MapStepArtifactsKubeToAPI),
Pvcs: common.MapMap(v.Pvcs, MapPvcConfigKubeToAPI),
}
}

Expand Down Expand Up @@ -1134,6 +1136,7 @@ func MapSpecKubeToAPI(v testworkflowsv1.TestWorkflowSpec) testkube.TestWorkflowS
After: common.MapSlice(v.After, MapStepKubeToAPI),
Events: common.MapSlice(v.Events, MapEventKubeToAPI),
Execution: common.MapPtr(v.Execution, MapTestWorkflowTagSchemaKubeToAPI),
Pvcs: common.MapMap(v.Pvcs, MapPvcConfigKubeToAPI),
}
}

Expand All @@ -1150,6 +1153,7 @@ func MapTemplateSpecKubeToAPI(v testworkflowsv1.TestWorkflowTemplateSpec) testku
After: common.MapSlice(v.After, MapIndependentStepKubeToAPI),
Events: common.MapSlice(v.Events, MapEventKubeToAPI),
Execution: common.MapPtr(v.Execution, MapTestWorkflowTagSchemaKubeToAPI),
Pvcs: common.MapMap(v.Pvcs, MapPvcConfigKubeToAPI),
}
}

Expand Down Expand Up @@ -1206,3 +1210,14 @@ func MapTestWorkflowTagSchemaKubeToAPI(v testworkflowsv1.TestWorkflowTagSchema)
Tags: v.Tags,
}
}

func MapPvcConfigKubeToAPI(v testworkflowsv1.TestWorkflowPvcConfig) testkube.TestWorkflowPvcConfig {
return testkube.TestWorkflowPvcConfig{
Shared: v.Shared,
AccessModes: v.AccessModes,
VolumeMode: v.VolumeMode,
Resources: common.MapPtr(v.Resources, MapResourcesKubeToAPI),
StorageClassName: v.StorageClassName,
Selector: common.MapPtr(v.Selector, MapSelectorToAPI),
}
}
15 changes: 15 additions & 0 deletions pkg/mapper/testworkflows/openapi_kube.go
Original file line number Diff line number Diff line change
Expand Up @@ -951,6 +951,7 @@ func MapStepParallelAPIToKube(v testkube.TestWorkflowStepParallel) testworkflows
Setup: common.MapSlice(v.Setup, MapStepAPIToKube),
Steps: common.MapSlice(v.Steps, MapStepAPIToKube),
After: common.MapSlice(v.After, MapStepAPIToKube),
Pvcs: common.MapMap(v.Pvcs, MapPvcConfigAPIToKube),
},
StepControl: testworkflowsv1.StepControl{
Paused: v.Paused,
Expand Down Expand Up @@ -995,6 +996,7 @@ func MapIndependentStepParallelAPIToKube(v testkube.TestWorkflowIndependentStepP
Setup: common.MapSlice(v.Setup, MapIndependentStepAPIToKube),
Steps: common.MapSlice(v.Steps, MapIndependentStepAPIToKube),
After: common.MapSlice(v.After, MapIndependentStepAPIToKube),
Pvcs: common.MapMap(v.Pvcs, MapPvcConfigAPIToKube),
},
StepControl: testworkflowsv1.StepControl{
Paused: v.Paused,
Expand Down Expand Up @@ -1234,6 +1236,7 @@ func MapSpecAPIToKube(v testkube.TestWorkflowSpec) testworkflowsv1.TestWorkflowS
Setup: common.MapSlice(v.Setup, MapStepAPIToKube),
Steps: common.MapSlice(v.Steps, MapStepAPIToKube),
After: common.MapSlice(v.After, MapStepAPIToKube),
Pvcs: common.MapMap(v.Pvcs, MapPvcConfigAPIToKube),
}
}

Expand All @@ -1253,6 +1256,7 @@ func MapTemplateSpecAPIToKube(v testkube.TestWorkflowTemplateSpec) testworkflows
Setup: common.MapSlice(v.Setup, MapIndependentStepAPIToKube),
Steps: common.MapSlice(v.Steps, MapIndependentStepAPIToKube),
After: common.MapSlice(v.After, MapIndependentStepAPIToKube),
Pvcs: common.MapMap(v.Pvcs, MapPvcConfigAPIToKube),
}
}

Expand Down Expand Up @@ -1485,3 +1489,14 @@ func MapTestWorkflowTagSchemaAPIToKube(v testkube.TestWorkflowTagSchema) testwor
Tags: v.Tags,
}
}

func MapPvcConfigAPIToKube(v testkube.TestWorkflowPvcConfig) testworkflowsv1.TestWorkflowPvcConfig {
return testworkflowsv1.TestWorkflowPvcConfig{
Shared: v.Shared,
vsukhin marked this conversation as resolved.
Show resolved Hide resolved
AccessModes: v.AccessModes,
VolumeMode: v.VolumeMode,
Resources: common.MapPtr(v.Resources, MapResourcesAPIToKube),
StorageClassName: v.StorageClassName,
Selector: common.MapPtr(v.Selector, MapLabelSelectorAPIToKube),
}
}
11 changes: 11 additions & 0 deletions pkg/testworkflows/testworkflowprocessor/bundle.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ type BundleOptions struct {
type Bundle struct {
Secrets []corev1.Secret
ConfigMaps []corev1.ConfigMap
Pvcs []corev1.PersistentVolumeClaim
Job batchv1.Job
Signature []stage.Signature
FullSignature []stage.Signature
Expand All @@ -50,6 +51,9 @@ func (b *Bundle) SetGroupId(groupId string) {
for i := range b.Secrets {
AnnotateGroupId(&b.Secrets[i], groupId)
}
for i := range b.Pvcs {
AnnotateGroupId(&b.Pvcs[i], groupId)
}
}

func (b *Bundle) Deploy(ctx context.Context, clientSet kubernetes.Interface, namespace string) (err error) {
Expand All @@ -68,6 +72,13 @@ func (b *Bundle) Deploy(ctx context.Context, clientSet kubernetes.Interface, nam
return errors.Wrap(err, "failed to deploy config maps")
}
}
for _, item := range b.Pvcs {
_, err = clientSet.CoreV1().PersistentVolumeClaims(namespace).Create(ctx, &item, metav1.CreateOptions{})
if err != nil {
return errors.Wrap(err, "failed to deploy pvcs")
}
}

_, err = clientSet.BatchV1().Jobs(namespace).Create(ctx, &b.Job, metav1.CreateOptions{})
return errors.Wrap(err, "failed to deploy job")
}
16 changes: 14 additions & 2 deletions pkg/testworkflows/testworkflowprocessor/intermediate.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,15 @@ type Intermediate interface {
ConfigMaps() []corev1.ConfigMap
Secrets() []corev1.Secret
Volumes() []corev1.Volume
Pvcs() []corev1.PersistentVolumeClaim

AppendJobConfig(cfg *testworkflowsv1.JobConfig) Intermediate
AppendPodConfig(cfg *testworkflowsv1.PodConfig) Intermediate

AddConfigMap(configMap corev1.ConfigMap) Intermediate
AddSecret(secret corev1.Secret) Intermediate
AddVolume(volume corev1.Volume) Intermediate
AddPvc(pvc corev1.PersistentVolumeClaim) Intermediate

AddEmptyDirVolume(source *corev1.EmptyDirVolumeSource, mountPath string) corev1.VolumeMount

Expand All @@ -47,8 +49,9 @@ type intermediate struct {
Job testworkflowsv1.JobConfig `expr:"include"`

// Actual Kubernetes resources to use
Secs []corev1.Secret `expr:"force"`
Cfgs []corev1.ConfigMap `expr:"force"`
Secs []corev1.Secret `expr:"force"`
Cfgs []corev1.ConfigMap `expr:"force"`
Ps []corev1.PersistentVolumeClaim `expr:"force"`

// Storing files
Files ConfigMapFiles `expr:"include"`
Expand Down Expand Up @@ -87,6 +90,10 @@ func (s *intermediate) Volumes() []corev1.Volume {
return append(s.Pod.Volumes, s.Files.Volumes()...)
}

func (s *intermediate) Pvcs() []corev1.PersistentVolumeClaim {
return s.Ps
}

func (s *intermediate) AppendJobConfig(cfg *testworkflowsv1.JobConfig) Intermediate {
s.Job = *testworkflowresolver.MergeJobConfig(&s.Job, cfg)
return s
Expand All @@ -102,6 +109,11 @@ func (s *intermediate) AddVolume(volume corev1.Volume) Intermediate {
return s
}

func (s *intermediate) AddPvc(pvc corev1.PersistentVolumeClaim) Intermediate {
s.Ps = append(s.Ps, pvc)
return s
}

func (s *intermediate) AddConfigMap(configMap corev1.ConfigMap) Intermediate {
s.Cfgs = append(s.Cfgs, configMap)
return s
Expand Down
11 changes: 11 additions & 0 deletions pkg/testworkflows/testworkflowprocessor/processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,16 @@ func (p *processor) Bundle(ctx context.Context, workflow *testworkflowsv1.TestWo
}
}

// Finalize Pvcs
pvcs := layer.Pvcs()
for i := range pvcs {
AnnotateControlledBy(&pvcs[i], options.Config.Resource.RootId, options.Config.Resource.Id)
err = expressions.FinalizeForce(&pvcs[i], machines...)
if err != nil {
return nil, errors.Wrap(err, "finalizing Pvc")
}
}

// Finalize Secrets
secrets := append(layer.Secrets(), options.Secrets...)
for i := range secrets {
Expand Down Expand Up @@ -420,6 +430,7 @@ func (p *processor) Bundle(ctx context.Context, workflow *testworkflowsv1.TestWo
bundle = &Bundle{
ConfigMaps: configMaps,
Secrets: secrets,
Pvcs: pvcs,
Job: jobSpec,
Signature: sig,
FullSignature: fullSig,
Expand Down
1 change: 1 addition & 0 deletions pkg/testworkflows/testworkflowresolver/apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ func injectTemplateToSpec(spec *testworkflowsv1.TestWorkflowSpec, template testw
spec.Services = MergeMap(common.MapMap(template.Spec.Services, ConvertIndependentServiceToService), spec.Services)
spec.Container = MergeContainerConfig(template.Spec.Container, spec.Container)
spec.System = MergeSystem(template.Spec.System, spec.System)
spec.Pvcs = MergeMap(template.Spec.Pvcs, spec.Pvcs)

// Include the steps from the template
setup := common.MapSlice(template.Spec.Setup, ConvertIndependentStepToStep)
Expand Down
33 changes: 33 additions & 0 deletions pkg/testworkflows/testworkflowresolver/merge.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"maps"

corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

testworkflowsv1 "github.com/kubeshop/testkube-operator/api/testworkflows/v1"
"github.com/kubeshop/testkube/internal/common"
Expand Down Expand Up @@ -414,3 +415,35 @@ func MergeTags(dst, src map[string]string) map[string]string {

return dst
}

func MergePvcConfig(dst, include *testworkflowsv1.TestWorkflowPvcConfig) *testworkflowsv1.TestWorkflowPvcConfig {
if dst == nil {
return include
} else if include == nil {
return dst
}
if include.Shared {
vsukhin marked this conversation as resolved.
Show resolved Hide resolved
dst.Shared = include.Shared
}
dst.AccessModes = append(dst.AccessModes, include.AccessModes...)
if include.VolumeMode != "" {
dst.VolumeMode = include.VolumeMode
}
dst.Resources = MergeResources(dst.Resources, include.Resources)
if include.StorageClassName != "" {
dst.StorageClassName = include.StorageClassName
}
dst.Selector = MergeLabelSelector(dst.Selector, include.Selector)
return dst
}

func MergeLabelSelector(dst, include *metav1.LabelSelector) *metav1.LabelSelector {
if dst == nil {
return include
} else if include == nil {
return dst
}
dst.MatchLabels = common.MergeMaps(dst.MatchLabels, include.MatchLabels)
dst.MatchExpressions = append(dst.MatchExpressions, include.MatchExpressions...)
return dst
}
Loading