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/apis/kops/v1alpha1"
|
||||||
"k8s.io/kops/pkg/kopscodecs"
|
"k8s.io/kops/pkg/kopscodecs"
|
||||||
"k8s.io/kops/upup/pkg/fi/cloudup"
|
"k8s.io/kops/upup/pkg/fi/cloudup"
|
||||||
|
"k8s.io/kops/util/pkg/text"
|
||||||
"k8s.io/kops/util/pkg/vfs"
|
"k8s.io/kops/util/pkg/vfs"
|
||||||
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
|
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
|
||||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
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
|
// 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 {
|
for _, section := range sections {
|
||||||
defaults := &schema.GroupVersionKind{
|
defaults := &schema.GroupVersionKind{
|
||||||
Group: v1alpha1.SchemeGroupVersion.Group,
|
Group: v1alpha1.SchemeGroupVersion.Group,
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"bytes"
|
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
|
|
@ -32,6 +30,7 @@ import (
|
||||||
"k8s.io/kops/pkg/apis/kops/v1alpha1"
|
"k8s.io/kops/pkg/apis/kops/v1alpha1"
|
||||||
"k8s.io/kops/pkg/kopscodecs"
|
"k8s.io/kops/pkg/kopscodecs"
|
||||||
"k8s.io/kops/pkg/sshcredentials"
|
"k8s.io/kops/pkg/sshcredentials"
|
||||||
|
"k8s.io/kops/util/pkg/text"
|
||||||
"k8s.io/kops/util/pkg/vfs"
|
"k8s.io/kops/util/pkg/vfs"
|
||||||
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
|
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
|
||||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
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 {
|
for _, section := range sections {
|
||||||
defaults := &schema.GroupVersionKind{
|
defaults := &schema.GroupVersionKind{
|
||||||
Group: v1alpha1.SchemeGroupVersion.Group,
|
Group: v1alpha1.SchemeGroupVersion.Group,
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@ limitations under the License.
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
|
|
@ -30,6 +29,7 @@ import (
|
||||||
kopsapi "k8s.io/kops/pkg/apis/kops"
|
kopsapi "k8s.io/kops/pkg/apis/kops"
|
||||||
"k8s.io/kops/pkg/commands"
|
"k8s.io/kops/pkg/commands"
|
||||||
"k8s.io/kops/pkg/kopscodecs"
|
"k8s.io/kops/pkg/kopscodecs"
|
||||||
|
"k8s.io/kops/util/pkg/text"
|
||||||
"k8s.io/kops/util/pkg/vfs"
|
"k8s.io/kops/util/pkg/vfs"
|
||||||
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
|
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
|
||||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
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)
|
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 {
|
for _, section := range sections {
|
||||||
o, gvk, err := kopscodecs.Decode(section, nil)
|
o, gvk, err := kopscodecs.Decode(section, nil)
|
||||||
|
|
|
||||||
|
|
@ -17,11 +17,11 @@ limitations under the License.
|
||||||
package kubemanifest
|
package kubemanifest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/ghodss/yaml"
|
"github.com/ghodss/yaml"
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
|
"k8s.io/kops/util/pkg/text"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Manifest struct {
|
type Manifest struct {
|
||||||
|
|
@ -32,7 +32,7 @@ func LoadManifestsFrom(contents []byte) ([]*Manifest, error) {
|
||||||
var manifests []*Manifest
|
var manifests []*Manifest
|
||||||
|
|
||||||
// TODO: Support more separators?
|
// TODO: Support more separators?
|
||||||
sections := bytes.Split(contents, []byte("\n---\n"))
|
sections := text.SplitContentToSections(contents)
|
||||||
|
|
||||||
for _, section := range sections {
|
for _, section := range sections {
|
||||||
data := make(map[string]interface{})
|
data := make(map[string]interface{})
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@ limitations under the License.
|
||||||
package testutils
|
package testutils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
|
@ -32,6 +31,7 @@ import (
|
||||||
"k8s.io/kops/pkg/diff"
|
"k8s.io/kops/pkg/diff"
|
||||||
"k8s.io/kops/pkg/kopscodecs"
|
"k8s.io/kops/pkg/kopscodecs"
|
||||||
"k8s.io/kops/upup/pkg/fi"
|
"k8s.io/kops/upup/pkg/fi"
|
||||||
|
"k8s.io/kops/util/pkg/text"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Model struct {
|
type Model struct {
|
||||||
|
|
@ -49,7 +49,7 @@ func LoadModel(basedir string) (*Model, error) {
|
||||||
|
|
||||||
spec := &Model{}
|
spec := &Model{}
|
||||||
|
|
||||||
sections := bytes.Split(clusterYaml, []byte("\n---\n"))
|
sections := text.SplitContentToSections(clusterYaml)
|
||||||
for _, section := range sections {
|
for _, section := range sections {
|
||||||
defaults := &schema.GroupVersionKind{
|
defaults := &schema.GroupVersionKind{
|
||||||
Group: v1alpha2.SchemeGroupVersion.Group,
|
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