Giter Site home page Giter Site logo

yaml-diff's Issues

detects properties without contents as diff

Test case:

package main

import (
	"bytes"
	"testing"

	"github.com/sters/yaml-diff/yamldiff"
	core "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/runtime"
	k8sJson "k8s.io/apimachinery/pkg/runtime/serializer/json"
)

var (
	k8sScheme         = runtime.NewScheme()
	k8sYamlSerializer = k8sJson.NewYAMLSerializer(k8sJson.DefaultMetaFactory, k8sScheme, k8sScheme)
)

var podYaml = `apiVersion: v1
kind: Pod
metadata:
  namespace: default
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx
`

func Test_PodYamlDiff(t *testing.T) {
	t.Parallel()

	yamlSource, err := yamldiff.Load(podYaml)
	if err != nil {
		t.Error(err)
	}

	buf := bytes.NewBuffer([]byte{})
	pod := &core.Pod{}

	_, _, err = k8sYamlSerializer.Decode([]byte(podYaml), nil, pod)
	if err != nil {
		t.Error(err)
	}

	err = k8sYamlSerializer.Encode(pod, buf)
	if err != nil {
		t.Error(err)
	}

	yamlParsed, err := yamldiff.Load(buf.String())
	if err != nil {
		t.Error(err)
	}

	diffs := yamldiff.Do(yamlSource, yamlParsed)
	if len(diffs) > 0 {
		for _, diff := range diffs {
			t.Log("diff detected\n" + diff.Dump())
		}

		t.Fail()
	}
}

Test result:

--- FAIL: Test_PodYamlDiff (0.01s)
    main_test.go:57: diff detected
          apiVersion: "v1"
          kind: "Pod"
          metadata:
            namespace: "default"
            name: "nginx"
            creationTimestamp: <nil>
          spec:
            containers:
              - 
                name: "nginx"
                image: "nginx"
        +       resources:
        + status:

It does not diff for creationTimestamp: <nil>, which seems to be a intentional, so this test case above should not throw a diff for empty properties either?

bug with yaml string wrapping syntax

Testcase:

package main

import (
	"testing"

	"github.com/sters/yaml-diff/yamldiff"
)

var yaml1 = `
value: |-
  foo
  bar
  baz
  special
    multiline
`

var yaml2 = `
value: "foo\nbar\nbaz\n\
special\n\
\  multiline"
`

func Test_PodYamlDiff(t *testing.T) {
	t.Parallel()

	yaml1Source, err := yamldiff.Load(yaml1)
	if err != nil {
		t.Error(err)
	}

	yaml2Source, err := yamldiff.Load(yaml2)
	if err != nil {
		t.Error(err)
	}

	diffs := yamldiff.Do(yaml1Source, yaml2Source)
	if len(diffs) > 0 {
		for _, diff := range diffs {
			if diff.Status() != yamldiff.DiffStatusSame {
				t.Log("diff detected\n" + diff.Dump())
				t.Fail()
			}
		}
	}
}

Result:

--- FAIL: Test_PodYamlDiff (0.00s)
    .../main_test.go:41: diff detected
        - value: "foo
        bar
        baz
        special
          multiline"
        + value: "foo
        bar
        baz
        \ special
        \ \  multiline"
        
FAIL

The handling of \n in strings seems to be fine, the issue seems to be:

  • the visual-only trailing \ indicating the line continues on the next line (baz -> special + special -> multiline)
  • and beginning \ indicating begin of space characters (multiline)
        ...\
        \  ...

I ran into a diff issue after using yq to manipulate some yaml files. The problem is not yq tho, the resulting yaml seems to be a correct yaml. If you copy those two yamls to e.g. https://www.yamldiff.com/ it doesn't yield a diff:
Screenshot_20221121_143822

bug with yaml long string

I want diff long string values, but give wrong result

test case

c.yaml

data:
  config: |
    logging.a: false
    logging.b: false

d.yaml

data:
  config: |
    logging.a: false
    logging.c: false

the d.yaml delete logging.b: false and add logging.c: false

but result:

--- example/c.ymal
+++ example/d.yaml

  data:
-   config: "logging.a: false
logging.b: false
"
+   config: "logging.a: false
logging.c: false

"

The correct result is
ๅ›พ็‰‡

ref:

[Feature Request] Add option (e.g. ZeroAsNull) to treat zero values equal to missing property (similiar to EmptyAsNull)

Test case:

package main

import (
	"testing"

	"github.com/sters/yaml-diff/yamldiff"
	"gopkg.in/yaml.v3"
)

var yaml1 = `
intA: 2
intB: 0
intC: 0
strA: foo
strB: ""
strC: ""
`

type MyType struct {
	IntA int    `yaml:"intA"`
	IntB int    `yaml:"intB"`
	IntC int    `yaml:"intC,omitempty"`
	StrA string `yaml:"strA"`
	StrB string `yaml:"strB"`
	StrC string `yaml:"strC,omitempty"`
}

func Test_YamlDiff_Omitempty(t *testing.T) {
	t.Parallel()

	yaml1Source, err := yamldiff.Load(yaml1)
	if err != nil {
		t.Error(err)
	}

	mytype := &MyType{}

	err = yaml.Unmarshal([]byte(yaml1), mytype)
	if err != nil {
		t.Error(err)
	}

	bYaml2, err := yaml.Marshal(mytype)
	if err != nil {
		t.Error(err)
	}

	yaml2 := string(bYaml2)

	yaml2Source, err := yamldiff.Load(yaml2)
	if err != nil {
		t.Error(err)
	}

	diffs := yamldiff.Do(yaml1Source, yaml2Source, yamldiff.EmptyAsNull())
	if len(diffs) > 0 {
		for _, diff := range diffs {
			if diff.Status() != yamldiff.DiffStatusSame {
				t.Log("diff detected\n" + diff.Dump())
				t.Fail()
			}
		}
	}
}

Test Result:

--- FAIL: Test_YamlDiff_Omitempty (0.00s)
    .../main_test.go:59: diff detected
          intA: 2
          intB: 0
        - intC: 0
          strA: "foo"
          strB: ""
        - strC: ""

If one of the diff sources contains a zero value for a property and the other has this property missing a diff will be found. This makes sense by default.

Kubernetes generates optional fields with omitempty tag (just looked up a random string property). So once a yaml is produced by kubernetes (e.g. kubectl), such output will have those properties missing. It's sometimes intentional by (because $reason) , that the other diff source has this property always set, even if set to zero.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.