mirror of https://github.com/kubernetes/kops.git
Correcly handle CRLF in the manifest
kops replace/create/delete now correctly handle crlf in the manifest. This fixes issue #6532
This commit is contained in:
parent
42a1aa5a23
commit
15bd566746
|
|
@ -31,6 +31,7 @@ import (
|
|||
"k8s.io/kops/pkg/apis/kops/v1alpha1"
|
||||
"k8s.io/kops/pkg/kopscodecs"
|
||||
"k8s.io/kops/upup/pkg/fi/cloudup"
|
||||
"k8s.io/kops/util/pkg/text"
|
||||
"k8s.io/kops/util/pkg/vfs"
|
||||
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
|
||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||
|
|
@ -136,7 +137,7 @@ func RunCreate(f *util.Factory, out io.Writer, c *CreateOptions) error {
|
|||
}
|
||||
}
|
||||
// TODO: this does not support a JSON array
|
||||
sections := bytes.Split(bytes.Replace(contents, []byte("\r\n"), []byte("\n"), -1), []byte("\n---\n"))
|
||||
sections := text.SplitContentToSections(contents)
|
||||
for _, section := range sections {
|
||||
defaults := &schema.GroupVersionKind{
|
||||
Group: v1alpha1.SchemeGroupVersion.Group,
|
||||
|
|
|
|||
|
|
@ -20,8 +20,6 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
|
||||
"bytes"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
|
|
@ -32,6 +30,7 @@ import (
|
|||
"k8s.io/kops/pkg/apis/kops/v1alpha1"
|
||||
"k8s.io/kops/pkg/kopscodecs"
|
||||
"k8s.io/kops/pkg/sshcredentials"
|
||||
"k8s.io/kops/util/pkg/text"
|
||||
"k8s.io/kops/util/pkg/vfs"
|
||||
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
|
||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||
|
|
@ -115,7 +114,7 @@ func RunDelete(factory *util.Factory, out io.Writer, d *DeleteOptions) error {
|
|||
}
|
||||
}
|
||||
|
||||
sections := bytes.Split(contents, []byte("\n---\n"))
|
||||
sections := text.SplitContentToSections(contents)
|
||||
for _, section := range sections {
|
||||
defaults := &schema.GroupVersionKind{
|
||||
Group: v1alpha1.SchemeGroupVersion.Group,
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ limitations under the License.
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
|
|
@ -30,6 +29,7 @@ import (
|
|||
kopsapi "k8s.io/kops/pkg/apis/kops"
|
||||
"k8s.io/kops/pkg/commands"
|
||||
"k8s.io/kops/pkg/kopscodecs"
|
||||
"k8s.io/kops/util/pkg/text"
|
||||
"k8s.io/kops/util/pkg/vfs"
|
||||
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
|
||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||
|
|
@ -107,7 +107,7 @@ func RunReplace(f *util.Factory, cmd *cobra.Command, out io.Writer, c *replaceOp
|
|||
return fmt.Errorf("error reading file %q: %v", f, err)
|
||||
}
|
||||
}
|
||||
sections := bytes.Split(contents, []byte("\n---\n"))
|
||||
sections := text.SplitContentToSections(contents)
|
||||
|
||||
for _, section := range sections {
|
||||
o, gvk, err := kopscodecs.Decode(section, nil)
|
||||
|
|
|
|||
|
|
@ -17,11 +17,11 @@ limitations under the License.
|
|||
package kubemanifest
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
|
||||
"github.com/ghodss/yaml"
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/kops/util/pkg/text"
|
||||
)
|
||||
|
||||
type Manifest struct {
|
||||
|
|
@ -32,7 +32,7 @@ func LoadManifestsFrom(contents []byte) ([]*Manifest, error) {
|
|||
var manifests []*Manifest
|
||||
|
||||
// TODO: Support more separators?
|
||||
sections := bytes.Split(contents, []byte("\n---\n"))
|
||||
sections := text.SplitContentToSections(contents)
|
||||
|
||||
for _, section := range sections {
|
||||
data := make(map[string]interface{})
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ limitations under the License.
|
|||
package testutils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
|
@ -32,6 +31,7 @@ import (
|
|||
"k8s.io/kops/pkg/diff"
|
||||
"k8s.io/kops/pkg/kopscodecs"
|
||||
"k8s.io/kops/upup/pkg/fi"
|
||||
"k8s.io/kops/util/pkg/text"
|
||||
)
|
||||
|
||||
type Model struct {
|
||||
|
|
@ -49,7 +49,7 @@ func LoadModel(basedir string) (*Model, error) {
|
|||
|
||||
spec := &Model{}
|
||||
|
||||
sections := bytes.Split(clusterYaml, []byte("\n---\n"))
|
||||
sections := text.SplitContentToSections(clusterYaml)
|
||||
for _, section := range sections {
|
||||
defaults := &schema.GroupVersionKind{
|
||||
Group: v1alpha2.SchemeGroupVersion.Group,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["format.go"],
|
||||
importpath = "k8s.io/kops/util/pkg/text",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//util/pkg/reflectutils:go_default_library",
|
||||
],
|
||||
)
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
Copyright 2019 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 text
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
)
|
||||
|
||||
// SplitContentToSections splits content of a kops manifest into sections.
|
||||
func SplitContentToSections(content []byte) [][]byte {
|
||||
|
||||
// replace windows line endings with unix ones
|
||||
normalized := bytes.Replace(content, []byte("\r\n"), []byte("\n"), -1)
|
||||
|
||||
return bytes.Split(normalized, []byte("\n---\n"))
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
Copyright 2019 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 text
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSplitToSections(t *testing.T) {
|
||||
tests := []struct {
|
||||
content []byte
|
||||
numSections int
|
||||
}{
|
||||
{
|
||||
content: []byte(""),
|
||||
numSections: 1,
|
||||
},
|
||||
{
|
||||
content: []byte("section 1"),
|
||||
numSections: 1,
|
||||
},
|
||||
{
|
||||
content: []byte("section 1\n"),
|
||||
numSections: 1,
|
||||
},
|
||||
{
|
||||
content: []byte("section 1\r\n"),
|
||||
numSections: 1,
|
||||
},
|
||||
{
|
||||
content: []byte("section 1\nanother line\n"),
|
||||
numSections: 1,
|
||||
},
|
||||
{
|
||||
content: []byte("section 1\r\nanother line\r\n"),
|
||||
numSections: 1,
|
||||
},
|
||||
{
|
||||
content: []byte("section 1\n---\nsection 2"),
|
||||
numSections: 2,
|
||||
},
|
||||
{
|
||||
content: []byte("section 1\r\n---\r\nsection 2"),
|
||||
numSections: 2,
|
||||
},
|
||||
{
|
||||
content: []byte("section 1\n\n---\n\nsection 2"),
|
||||
numSections: 2,
|
||||
},
|
||||
{
|
||||
content: []byte("section 1\r\n\r\n---\r\n\r\nsection 2"),
|
||||
numSections: 2,
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
ns := len(SplitContentToSections(test.content))
|
||||
if ns != test.numSections {
|
||||
t.Errorf("Expected %v, got %v sections for content %q", test.numSections, ns, string(test.content))
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue