sters / yaml-diff Goto Github PK
View Code? Open in Web Editor NEWMake a diff between 2 yaml files.
License: MIT License
Make a diff between 2 yaml files.
License: MIT License
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:
\
indicating the line continues on the next line (baz
-> special
+ special
-> multiline
)\
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:
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?
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
"
ref:
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.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.