Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
K
ksonnet
Manage
Activity
Members
Labels
Plan
Issues
0
Issue boards
Milestones
Wiki
Requirements
Code
Merge requests
0
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Container Registry
Operate
Environments
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Ijaz Ahmad
ksonnet
Commits
01e5f51b
Commit
01e5f51b
authored
7 years ago
by
Angus Lees
Browse files
Options
Downloads
Patches
Plain Diff
Implement diff subcommand
Uses github.com/yudai/gojsondiff for the heavy lifting.
parent
5f4a09c5
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
cmd/delete.go
+2
-1
2 additions, 1 deletion
cmd/delete.go
cmd/diff.go
+96
-0
96 additions, 0 deletions
cmd/diff.go
cmd/update.go
+2
-1
2 additions, 1 deletion
cmd/update.go
utils/sort.go
+23
-16
23 additions, 16 deletions
utils/sort.go
utils/sort_test.go
+45
-9
45 additions, 9 deletions
utils/sort_test.go
with
168 additions
and
27 deletions
cmd/delete.go
+
2
−
1
View file @
01e5f51b
...
...
@@ -2,6 +2,7 @@ package cmd
import
(
"fmt"
"sort"
"github.com/golang/glog"
"github.com/spf13/cobra"
...
...
@@ -44,7 +45,7 @@ var deleteCmd = &cobra.Command{
defaultNs
,
_
,
err
:=
clientConfig
.
Namespace
()
utils
.
SortDepLast
(
objs
)
sort
.
Sort
(
sort
.
Reverse
(
utils
.
DependencyOrder
(
objs
)
))
deleteOpts
:=
v1
.
DeleteOptions
{
OrphanDependents
:
&
boolFalse
}
if
gracePeriod
>=
0
{
...
...
This diff is collapsed.
Click to expand it.
cmd/diff.go
0 → 100644
+
96
−
0
View file @
01e5f51b
package
cmd
import
(
"fmt"
"io"
"os"
"sort"
"github.com/golang/glog"
"github.com/mattn/go-isatty"
"github.com/spf13/cobra"
"github.com/yudai/gojsondiff"
"github.com/yudai/gojsondiff/formatter"
"k8s.io/client-go/pkg/api/errors"
"github.com/ksonnet/kubecfg/utils"
)
func
init
()
{
RootCmd
.
AddCommand
(
diffCmd
)
}
var
diffCmd
=
&
cobra
.
Command
{
Use
:
"diff"
,
Short
:
"Display differences between server and local config"
,
RunE
:
func
(
cmd
*
cobra
.
Command
,
args
[]
string
)
error
{
out
:=
cmd
.
OutOrStdout
()
objs
,
err
:=
readObjs
(
cmd
,
args
)
if
err
!=
nil
{
return
err
}
clientpool
,
disco
,
err
:=
restClientPool
(
cmd
)
if
err
!=
nil
{
return
err
}
defaultNs
,
_
,
err
:=
clientConfig
.
Namespace
()
if
err
!=
nil
{
return
err
}
sort
.
Sort
(
utils
.
AlphabeticalOrder
(
objs
))
for
_
,
obj
:=
range
objs
{
desc
:=
fmt
.
Sprintf
(
"%s/%s"
,
obj
.
GetKind
(),
fqName
(
obj
))
glog
.
V
(
2
)
.
Info
(
"Fetching "
,
desc
)
c
,
err
:=
clientForResource
(
clientpool
,
disco
,
obj
,
defaultNs
)
if
err
!=
nil
{
return
err
}
liveObj
,
err
:=
c
.
Get
(
obj
.
GetName
())
if
err
!=
nil
&&
errors
.
IsNotFound
(
err
)
{
glog
.
V
(
2
)
.
Infof
(
"%s doesn't exist on the server"
,
desc
)
liveObj
=
nil
}
else
if
err
!=
nil
{
return
fmt
.
Errorf
(
"Error fetching %s: %v"
,
desc
,
err
)
}
fmt
.
Fprintln
(
out
,
"---"
)
fmt
.
Fprintf
(
out
,
"- live %s
\n
+ config %s"
,
desc
,
desc
)
if
liveObj
==
nil
{
fmt
.
Fprintf
(
out
,
"%s doesn't exist on server
\n
"
,
desc
)
continue
}
diff
:=
gojsondiff
.
New
()
.
CompareObjects
(
liveObj
.
Object
,
obj
.
Object
)
if
diff
.
Modified
()
{
fcfg
:=
formatter
.
AsciiFormatterConfig
{
Coloring
:
istty
(
out
),
}
formatter
:=
formatter
.
NewAsciiFormatter
(
liveObj
.
Object
,
fcfg
)
text
,
err
:=
formatter
.
Format
(
diff
)
if
err
!=
nil
{
return
err
}
fmt
.
Fprintf
(
out
,
"%s"
,
text
)
}
else
{
fmt
.
Fprintf
(
out
,
"%s unchanged
\n
"
,
desc
)
}
}
return
nil
},
}
func
istty
(
w
io
.
Writer
)
bool
{
if
f
,
ok
:=
w
.
(
*
os
.
File
);
ok
{
return
isatty
.
IsTerminal
(
f
.
Fd
())
}
return
false
}
This diff is collapsed.
Click to expand it.
cmd/update.go
+
2
−
1
View file @
01e5f51b
...
...
@@ -3,6 +3,7 @@ package cmd
import
(
"encoding/json"
"fmt"
"sort"
"github.com/golang/glog"
"github.com/spf13/cobra"
...
...
@@ -49,7 +50,7 @@ var updateCmd = &cobra.Command{
return
err
}
utils
.
SortDepFirst
(
objs
)
sort
.
Sort
(
utils
.
DependencyOrder
(
objs
)
)
for
_
,
obj
:=
range
objs
{
desc
:=
fmt
.
Sprintf
(
"%s/%s"
,
obj
.
GetKind
(),
fqName
(
obj
))
...
...
This diff is collapsed.
Click to expand it.
utils/sort.go
+
23
−
16
View file @
01e5f51b
package
utils
import
(
"sort"
"k8s.io/client-go/pkg/api/unversioned"
"k8s.io/client-go/pkg/runtime"
)
...
...
@@ -42,23 +40,32 @@ func depTier(o *runtime.Unstructured) int {
}
}
type
dependentObjects
[]
*
runtime
.
Unstructured
// DependencyOrder is a `sort.Interface` that *best-effort* sorts the
// objects so that known dependencies appear earlier in the list. The
// idea is to prevent *some* of the "crash-restart" loops when
// creating inter-dependent resources.
type
DependencyOrder
[]
*
runtime
.
Unstructured
func
(
l
d
ependen
tObjects
)
Len
()
int
{
return
len
(
l
)
}
func
(
l
d
ependen
tObjects
)
Swap
(
i
,
j
int
)
{
l
[
i
],
l
[
j
]
=
l
[
j
],
l
[
i
]
}
func
(
l
d
ependen
tObjects
)
Less
(
i
,
j
int
)
bool
{
func
(
l
D
ependen
cyOrder
)
Len
()
int
{
return
len
(
l
)
}
func
(
l
D
ependen
cyOrder
)
Swap
(
i
,
j
int
)
{
l
[
i
],
l
[
j
]
=
l
[
j
],
l
[
i
]
}
func
(
l
D
ependen
cyOrder
)
Less
(
i
,
j
int
)
bool
{
return
depTier
(
l
[
i
])
<
depTier
(
l
[
j
])
}
// SortDepFirst *best-effort* sorts the objects so that known
// dependencies appear earlier in the list. The idea is to prevent
// *some* of the "crash-restart" loops when creating inter-dependent
// resources.
func
SortDepFirst
(
objs
[]
*
runtime
.
Unstructured
)
{
sort
.
Sort
(
dependentObjects
(
objs
))
}
// AlphabeticalOrder is a `sort.Interface` that sorts the
// objects by namespace/name/kind alphabetical order
type
AlphabeticalOrder
[]
*
runtime
.
Unstructured
func
(
l
AlphabeticalOrder
)
Len
()
int
{
return
len
(
l
)
}
func
(
l
AlphabeticalOrder
)
Swap
(
i
,
j
int
)
{
l
[
i
],
l
[
j
]
=
l
[
j
],
l
[
i
]
}
func
(
l
AlphabeticalOrder
)
Less
(
i
,
j
int
)
bool
{
a
,
b
:=
l
[
i
],
l
[
j
]
// SortDepLast is the reverse order of SortDepFirst.
func
SortDepLast
(
objs
[]
*
runtime
.
Unstructured
)
{
sort
.
Sort
(
sort
.
Reverse
(
dependentObjects
(
objs
)))
if
a
.
GetNamespace
()
!=
b
.
GetNamespace
()
{
return
a
.
GetNamespace
()
<
b
.
GetNamespace
()
}
if
a
.
GetName
()
!=
b
.
GetName
()
{
return
a
.
GetName
()
<
b
.
GetName
()
}
return
a
.
GetKind
()
<
b
.
GetKind
()
}
This diff is collapsed.
Click to expand it.
utils/sort_test.go
+
45
−
9
View file @
01e5f51b
package
utils
import
(
"reflect"
"sort"
"testing"
"k8s.io/client-go/pkg/runtime"
)
func
newObj
(
apiVersion
,
kind
string
)
*
runtime
.
Unstructured
{
return
&
runtime
.
Unstructured
{
Object
:
map
[
string
]
interface
{}{
"apiVersion"
:
apiVersion
,
"kind"
:
kind
,
},
var
_
sort
.
Interface
=
DependencyOrder
{}
func
TestDepSort
(
t
*
testing
.
T
)
{
newObj
:=
func
(
apiVersion
,
kind
string
)
*
runtime
.
Unstructured
{
return
&
runtime
.
Unstructured
{
Object
:
map
[
string
]
interface
{}{
"apiVersion"
:
apiVersion
,
"kind"
:
kind
,
},
}
}
}
func
TestSort
(
t
*
testing
.
T
)
{
objs
:=
[]
*
runtime
.
Unstructured
{
newObj
(
"extensions/v1beta1"
,
"Deployment"
),
newObj
(
"v1"
,
"ConfigMap"
),
...
...
@@ -23,7 +27,7 @@ func TestSort(t *testing.T) {
newObj
(
"v1"
,
"Service"
),
}
SortDep
First
(
objs
)
sort
.
Sort
(
Dep
endencyOrder
(
objs
)
)
if
objs
[
0
]
.
GetKind
()
!=
"Namespace"
{
t
.
Error
(
"Namespace should be sorted first"
)
...
...
@@ -32,3 +36,35 @@ func TestSort(t *testing.T) {
t
.
Error
(
"Deployment should be sorted after other objects"
)
}
}
func
TestAlphaSort
(
t
*
testing
.
T
)
{
newObj
:=
func
(
ns
,
name
,
kind
string
)
*
runtime
.
Unstructured
{
o
:=
runtime
.
Unstructured
{}
o
.
SetNamespace
(
ns
)
o
.
SetName
(
name
)
o
.
SetKind
(
kind
)
return
&
o
}
objs
:=
[]
*
runtime
.
Unstructured
{
newObj
(
"default"
,
"mysvc"
,
"Deployment"
),
newObj
(
""
,
"default"
,
"StorageClass"
),
newObj
(
""
,
"default"
,
"ClusterRole"
),
newObj
(
"default"
,
"mydeploy"
,
"Deployment"
),
newObj
(
"default"
,
"mysvc"
,
"Secret"
),
}
expected
:=
[]
*
runtime
.
Unstructured
{
objs
[
2
],
objs
[
1
],
objs
[
3
],
objs
[
0
],
objs
[
4
],
}
sort
.
Sort
(
AlphabeticalOrder
(
objs
))
if
!
reflect
.
DeepEqual
(
objs
,
expected
)
{
t
.
Errorf
(
"actual != expected: %v != %v"
,
objs
,
expected
)
}
}
This diff is collapsed.
Click to expand it.
Preview
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment