Skip to content
This repository has been archived by the owner on Aug 12, 2024. It is now read-only.

Commit

Permalink
Initial commit with diff package
Browse files Browse the repository at this point in the history
  • Loading branch information
[email protected] committed May 19, 2021
0 parents commit 9901549
Show file tree
Hide file tree
Showing 10 changed files with 2,208 additions and 0 deletions.
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Copyright (c) 2021, Oracle and/or its affiliates.
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
vendor
# Temporary Build Files
build/_output
build/_test
.idea
known_licenses.txt
no_licenses.txt
thirdparty_licenses
37 changes: 37 additions & 0 deletions LICENSE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
Copyright (c) 2021 Oracle America, Inc. and its affiliates.

The Universal Permissive License (UPL), Version 1.0

Subject to the condition set forth below, permission is hereby granted to any
person obtaining a copy of this software, associated documentation and/or data
(collectively the "Software"), free of charge and under any and all copyright
rights in the Software, and any and all patent rights owned or freely licensable
by each licensor hereunder covering either (i) the unmodified Software as
contributed to or provided by such licensor, or (ii) the Larger Works (as
defined below), to deal in both

(a) the Software, and

(b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
one is included with the Software (each a ¿Larger Work¿ to which the Software
is contributed by such licensors),

without restriction, including without limitation the rights to copy, create
derivative works of, display, perform, and distribute the Software and make,
use, sell, offer for sale, import, export, have made, and have sold the
Software and the Larger Work(s), and to sublicense the foregoing rights on
either these or other terms.

This license is subject to the following condition:

The above copyright notice and either this complete permission notice or at a
minimum a reference to the UPL must be included in all copies or substantial
portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
25 changes: 25 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Copyright (c) 2021, Oracle and/or its affiliates.
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.

GO ?= GO111MODULE=on go

.PHONY: go-build
go-build:
$(GO) build ./...

.PHONY: go-test
go-test: go-build
$(GO) test ./...

.PHONY: go-lint
go-lint: install-linter
golangci-lint run -E misspell,gofmt,goimports ./...

.PHONY: install-linter
install-linter:
ifeq (, $(shell command -v golangci-lint))
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $$(go env GOPATH)/bin v1.38.0
$(eval LINTER=$(GOPATH)/bin/golangci-lint)
else
$(eval LINTER=$(shell command -v golangci-lint))
endif
65 changes: 65 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Kubernetes Golang Utilities for Verrazzano

This repository is a collection of general-purpose, Kubernetes-related Golang utilities used across
[Verrazzano](https://github.com/verrazzano).

## How to use

To import within your project, run:
```
go get github.com/verrazzano/pkg
```

See below for specific examples of using the various packages.

## Packages

### ./diff: Kubernetes Object Comparator

The utilities in this package are intended to be in used in the context of custom Kubernetes controllers,
when comparing the live state of a Kubernetes object (fetched via API) with its desired state (constructed
via code). The "live" object, fetched from Kubernetes, will auto-generate many fields that we won't
or can't specify in the "desired" object that we construct. A common job of a Kubernetes controller is to
compare a desired and live object, and `Apply()` changes if they are different. But we don't want these
auto-generated fields to cause us to apply changes. A standard Golang struct comparison _will_ detect these
as differences, and is therefore insufficient for our purposes here.

Our `Diff()` function simply performs a recursive struct comparison that ignores any fields that were unspecified
in the `toObject` (the desired object):

```
import (
"github.com/verrazzano/pkg/diff"
)
```

Example: Detecting changes to a deployment object:

Fetch the live Kubernetes object:
```
cfg, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
if err != nil {
log.Fatal(err)
}
kubeClientSet, err := kubernetes.NewForConfig(cfg)
if err != nil {
log.Fatal(err)
}
kubeInformerFactory := kubeinformers.NewSharedInformerFactory(kubeClientSet, 30*time.Second)
deploymentInformer := kubeInformerFactory.Apps().V1().Deployments()
deploymentLister := deploymentInformer.Lister()
liveDeployment := deploymentsLister.Deployments("mynamespace").Get("mydeployment")
```

Construct your desired object:
```
desiredDeployment := createMyDeploymentObject()
```

Compare:
```
diffs := diff.Diff(liveDeployment, desiredDeployment)
if diffs != "" {
fmt.Println("Diffs: " + diffs)
}
```
18 changes: 18 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Reporting Security Vulnerabilities

Oracle values the independent security research community and believes that responsible disclosure of security vulnerabilities helps us ensure the security and privacy of all our users.

Please do NOT raise a GitHub Issue to report a security vulnerability. If you believe you have found a security vulnerability, please submit a report to [email protected] preferably with a proof of concept. We provide additional information on [how to report security vulnerabilities to Oracle](https://www.oracle.com/corporate/security-practices/assurance/vulnerability/reporting.html) which includes public encryption keys for secure email.

We ask that you do not use other channels or contact project contributors directly.

Non-vulnerability related security issues such as new great new ideas for security features are welcome on GitHub Issues.

## Security Updates, Alerts and Bulletins

Security updates will be released on a regular cadence. Many of our projects will typically release security fixes in conjunction with the [Oracle Critical Patch Update](https://www.oracle.com/security-alerts/) program. Security updates are released on the Tuesday closest to the 17th day of January, April, July and October. A pre-release announcement will be published on the Thursday preceding each release. Additional information, including past advisories, is available on our [Security Alerts](https://www.oracle.com/security-alerts/) page.

## Security-Related Information

We will provide security related information such as a threat model, considerations for secure use, or any known security issues in our documentation. Please note that labs and sample code are intended to demonstrate a concept and may not be sufficiently hardened for production use.

88 changes: 88 additions & 0 deletions THIRD_PARTY_LICENSES.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
github.com/verrazzano/pkg
-------- Copyrights
Copyright (c) 2020 Oracle America, Inc. and its affiliates.
Copyright (C) 2021, Oracle and/or its affiliates.

-------- License
Copyright (c) 2020 Oracle America, Inc. and its affiliates.

The Universal Permissive License (UPL), Version 1.0

Subject to the condition set forth below, permission is hereby granted to any
person obtaining a copy of this software, associated documentation and/or data
(collectively the "Software"), free of charge and under any and all copyright
rights in the Software, and any and all patent rights owned or freely licensable
by each licensor hereunder covering either (i) the unmodified Software as
contributed to or provided by such licensor, or (ii) the Larger Works (as
defined below), to deal in both

(a) the Software, and

(b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
one is included with the Software (each a ¿Larger Work¿ to which the Software
is contributed by such licensors),

without restriction, including without limitation the rights to copy, create
derivative works of, display, perform, and distribute the Software and make,
use, sell, offer for sale, import, export, have made, and have sold the
Software and the Larger Work(s), and to sublicense the foregoing rights on
either these or other terms.

This license is subject to the following condition:

The above copyright notice and either this complete permission notice or at a
minimum a reference to the UPL must be included in all copies or substantial
portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.


----------------------- Dependencies Grouped by License ------------
-------- Dependency
github.com/google/go-cmp
-------- Copyrights
Copyright (c) 2017 The Go Authors. All rights reserved.
Copyright 2017, The Go Authors. All rights reserved.
Copyright 2018, The Go Authors. All rights reserved.
Copyright 2019, The Go Authors. All rights reserved.
Copyright 2020, The Go Authors. All rights reserved.

-------- Dependencies Summary
github.com/google/go-cmp

-------- License used by Dependencies
SPDX:BSD-3-Clause--modified-by-Google
Redistribution and use in source and binary forms, with
or without modification, are permitted provided that the following conditions
are met:

* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

ATTRIBUTION-HELPER-GENERATED:
License file based on go.mod with md5 sum: ceeb284685d01c120a0c982ef88a56e7
84 changes: 84 additions & 0 deletions diff/diff.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// Copyright (C) 2021, Oracle and/or its affiliates.
// Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.

// Package diff provides utilities for diffing Kubernetes objects.
//
// The utilities in this package are intended to be in used in the context of
// Kubernetes controllers, when comparing the live state of a Kubernetes
// object with its desired state.
package diff

import (
"fmt"
"reflect"
"time"

"github.com/google/go-cmp/cmp"
)

//
// Diff diffs two Golang objects recursively, but treats any elements whose values are empty
// in the 'fromObject' as "no diff". This is useful when comparing a desired Kubernetes object against a
// live Kubernetes object:
// 1) The 'fromObject' is constructed via code, and doesn't specify a value for every nested field in the struct.
// Most Kubernetes object structs have an enormous number of fields, and it's not feasible to try to set them all
// when constructing the object. Also, note that some fields in the structs (like UUID, resourceVersion, or
// creationTime), are completely determined by Kubernetes at runtime.
// 2) The 'toObject' has been retrieved via the Kubernetes API, and has had many of the fields that were unspecified
// in the fromObject populated with Kubernetes-generated values.
// In this situation, to determine whether our fromObject is truly different than the toObject, we ignore processing
// of elements whose values are empty in the fromObject.
//
func Diff(fromObject interface{}, toObject interface{}) string {
return cmp.Diff(fromObject, toObject, IgnoreUnset())
}

// Extended from https://github.com/kubernetes/apimachinery/blob/master/pkg/util/diff/diff.go
// IgnoreUnset return a cmp.Option to ignore changes for values that are unset in the toObject
func IgnoreUnset() cmp.Option {
return cmp.Options{
// ignore unset fields in v2
cmp.FilterPath(func(path cmp.Path) bool {
_, v2 := path.Last().Values()

switch v2.Kind() {
case reflect.Slice, reflect.Map:
if v2.IsNil() || v2.Len() == 0 {
return true
}
case reflect.String:
if v2.Len() == 0 {
return true
}
case reflect.Interface, reflect.Ptr:
if v2.IsNil() {
return true
}
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64:
if v2.IsZero() {
return true
}
case reflect.Struct:
{
// Handle empty Time value
if v2.Type() == reflect.TypeOf(time.Time{}) {
if fmt.Sprintf("%s", v2) == "0001-01-01 00:00:00 +0000 UTC" {
return true
}
}
}
}
return false
}, cmp.Ignore()),
// ignore map entries that aren't set in v2
cmp.FilterPath(func(path cmp.Path) bool {
switch i := path.Last().(type) {
case cmp.MapIndex:
if _, v2 := i.Values(); !v2.IsValid() {
return true
}
}
return false
}, cmp.Ignore()),
}
}
Loading

0 comments on commit 9901549

Please sign in to comment.