diff --git a/pkg/server/container_update_resources.go b/pkg/server/container_update_resources.go index 97189d033..87704fe89 100644 --- a/pkg/server/container_update_resources.go +++ b/pkg/server/container_update_resources.go @@ -28,10 +28,10 @@ import ( runtimespec "github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/runtime-tools/generate" "golang.org/x/net/context" - "k8s.io/apimachinery/pkg/conversion" "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" containerstore "github.com/kubernetes-incubator/cri-containerd/pkg/store/container" + "github.com/kubernetes-incubator/cri-containerd/pkg/util" ) // UpdateContainerResources updates ContainerConfig of the container. @@ -129,11 +129,11 @@ func updateContainerSpec(ctx context.Context, cntr containerd.Container, spec *r // updateOCILinuxResource updates container resource limit. func updateOCILinuxResource(spec *runtimespec.Spec, new *runtime.LinuxContainerResources) (*runtimespec.Spec, error) { // Copy to make sure old spec is not changed. - cloned, err := conversion.NewCloner().DeepCopy(spec) - if err != nil { + var cloned runtimespec.Spec + if err := util.DeepCopy(&cloned, spec); err != nil { return nil, fmt.Errorf("failed to deep copy: %v", err) } - g := generate.NewFromSpec(cloned.(*runtimespec.Spec)) + g := generate.NewFromSpec(&cloned) if new.GetCpuPeriod() != 0 { g.SetLinuxResourcesCPUPeriod(uint64(new.GetCpuPeriod())) diff --git a/pkg/util/deep_copy.go b/pkg/util/deep_copy.go new file mode 100644 index 000000000..fb3521843 --- /dev/null +++ b/pkg/util/deep_copy.go @@ -0,0 +1,41 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package util + +import ( + "encoding/json" + "fmt" +) + +// DeepCopy makes a deep copy from src into dst. +func DeepCopy(dst interface{}, src interface{}) error { + if dst == nil { + return fmt.Errorf("dst cannot be nil") + } + if src == nil { + return fmt.Errorf("src cannot be nil") + } + bytes, err := json.Marshal(src) + if err != nil { + return fmt.Errorf("unable to marshal src: %s", err) + } + err = json.Unmarshal(bytes, dst) + if err != nil { + return fmt.Errorf("unable to unmarshal into dst: %s", err) + } + return nil +} diff --git a/pkg/util/deep_copy_test.go b/pkg/util/deep_copy_test.go new file mode 100644 index 000000000..df85bad0d --- /dev/null +++ b/pkg/util/deep_copy_test.go @@ -0,0 +1,63 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package util + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +type A struct { + String string + Int int + Strings []string + Ints map[string]int + As map[string]*A +} + +func TestCopy(t *testing.T) { + src := &A{ + String: "Hello World", + Int: 5, + Strings: []string{"A", "B"}, + Ints: map[string]int{"A": 1, "B": 2, "C": 4}, + As: map[string]*A{ + "One": {String: "2"}, + "Two": {String: "3"}, + }, + } + dst := &A{ + Strings: []string{"C"}, + Ints: map[string]int{"B": 3, "C": 4}, + As: map[string]*A{"One": {String: "1", Int: 5}}, + } + expected := &A{ + String: "Hello World", + Int: 5, + Strings: []string{"A", "B"}, + Ints: map[string]int{"A": 1, "B": 2, "C": 4}, + As: map[string]*A{ + "One": {String: "2"}, + "Two": {String: "3"}, + }, + } + assert.NotEqual(t, expected, dst) + err := DeepCopy(dst, src) + assert.NoError(t, err) + assert.Equal(t, expected, dst) +}