Skip to content

Commit 89c4668

Browse files
authored
[INS-1352] show deleted teams when using dry run (#276)
* add support for --delete on teams push dry-run * bump some libraries
1 parent 2d7eb1d commit 89c4668

3 files changed

Lines changed: 91 additions & 35 deletions

File tree

go.mod

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@ require (
99
github.com/fatih/color v1.18.0
1010
github.com/google/go-cmp v0.7.0
1111
github.com/hashicorp/go-multierror v1.1.1
12-
github.com/imroc/req/v3 v3.54.0
12+
github.com/imroc/req/v3 v3.54.2
1313
github.com/open-policy-agent/opa v1.7.1
1414
github.com/rogpeppe/go-internal v1.14.1
1515
github.com/samber/lo v1.51.0
1616
github.com/sirupsen/logrus v1.9.3
17-
github.com/spf13/cobra v1.9.1
18-
github.com/stretchr/testify v1.10.0
17+
github.com/spf13/cobra v1.10.1
18+
github.com/stretchr/testify v1.11.1
1919
github.com/xlab/treeprint v1.2.0
20-
golang.org/x/net v0.42.0
20+
golang.org/x/net v0.43.0
2121
gopkg.in/yaml.v2 v2.4.0
2222
gopkg.in/yaml.v3 v3.0.1
2323
k8s.io/apimachinery v0.33.3
@@ -71,7 +71,7 @@ require (
7171
github.com/quic-go/quic-go v0.53.0 // indirect
7272
github.com/rcrowley/go-metrics v0.0.0-20250401214520-65e299d6c5c9 // indirect
7373
github.com/refraction-networking/utls v1.7.3 // indirect
74-
github.com/spf13/pflag v1.0.7 // indirect
74+
github.com/spf13/pflag v1.0.9 // indirect
7575
github.com/tchap/go-patricia/v2 v2.3.3 // indirect
7676
github.com/vektah/gqlparser/v2 v2.5.30 // indirect
7777
github.com/x448/float16 v0.8.4 // indirect
@@ -86,13 +86,13 @@ require (
8686
go.uber.org/mock v0.5.2 // indirect
8787
go.yaml.in/yaml/v2 v2.4.2 // indirect
8888
go.yaml.in/yaml/v3 v3.0.4 // indirect
89-
golang.org/x/crypto v0.40.0 // indirect
89+
golang.org/x/crypto v0.41.0 // indirect
9090
golang.org/x/mod v0.26.0 // indirect
9191
golang.org/x/oauth2 v0.30.0 // indirect
9292
golang.org/x/sync v0.16.0 // indirect
93-
golang.org/x/sys v0.34.0 // indirect
94-
golang.org/x/term v0.33.0 // indirect
95-
golang.org/x/text v0.27.0 // indirect
93+
golang.org/x/sys v0.35.0 // indirect
94+
golang.org/x/term v0.34.0 // indirect
95+
golang.org/x/text v0.28.0 // indirect
9696
golang.org/x/time v0.12.0 // indirect
9797
golang.org/x/tools v0.35.0 // indirect
9898
gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect

go.sum

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,8 @@ github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+l
9898
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
9999
github.com/icholy/digest v1.1.0 h1:HfGg9Irj7i+IX1o1QAmPfIBNu/Q5A5Tu3n/MED9k9H4=
100100
github.com/icholy/digest v1.1.0/go.mod h1:QNrsSGQ5v7v9cReDI0+eyjsXGUoRSUZQHeQ5C4XLa0Y=
101-
github.com/imroc/req/v3 v3.54.0 h1:kwWJSpT7OvjJ/Q8ykp+69Ye5H486RKDcgEoepw1Ren4=
102-
github.com/imroc/req/v3 v3.54.0/go.mod h1:P8gCJjG/XNUFeP6WOi40VAXfYwT+uPM00xvoBWiwzUQ=
101+
github.com/imroc/req/v3 v3.54.2 h1:1eWvCPiz3mSwap7HWqdHN2biuoue+n+mpYWsYiXeMB0=
102+
github.com/imroc/req/v3 v3.54.2/go.mod h1:nR52xB4Ogdwst/UW3QLb2wUiR9ZCLYhiLX9iyksae0I=
103103
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
104104
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
105105
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
@@ -167,18 +167,17 @@ github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw=
167167
github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
168168
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
169169
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
170-
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
171-
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
172-
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
173-
github.com/spf13/pflag v1.0.7 h1:vN6T9TfwStFPFM5XzjsvmzZkLuaLX+HS+0SeFLRgU6M=
174-
github.com/spf13/pflag v1.0.7/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
170+
github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s=
171+
github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0=
172+
github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY=
173+
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
175174
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
176175
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
177176
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
178177
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
179178
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
180-
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
181-
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
179+
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
180+
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
182181
github.com/tchap/go-patricia/v2 v2.3.3 h1:xfNEsODumaEcCcY3gI0hYPZ/PcpVv5ju6RMAhgwZDDc=
183182
github.com/tchap/go-patricia/v2 v2.3.3/go.mod h1:VZRHKAb53DLaG+nA9EaYYiaEx6YztwDlLElMsnSHD4k=
184183
github.com/vektah/gqlparser/v2 v2.5.30 h1:EqLwGAFLIzt1wpx1IPpY67DwUujF1OfzgEyDsLrN6kE=
@@ -232,8 +231,8 @@ go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
232231
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
233232
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
234233
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
235-
golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM=
236-
golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY=
234+
golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
235+
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
237236
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
238237
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
239238
golang.org/x/mod v0.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg=
@@ -242,8 +241,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
242241
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
243242
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
244243
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
245-
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
246-
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
244+
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
245+
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
247246
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
248247
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
249248
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -256,14 +255,14 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
256255
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
257256
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
258257
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
259-
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
260-
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
261-
golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg=
262-
golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0=
258+
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
259+
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
260+
golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4=
261+
golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw=
263262
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
264263
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
265-
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
266-
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
264+
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
265+
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
267266
golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
268267
golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
269268
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=

pkg/teams/teams.go

Lines changed: 64 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,23 +21,27 @@ import (
2121
"os"
2222

2323
"github.com/imroc/req/v3"
24+
"github.com/samber/lo"
2425
"github.com/sirupsen/logrus"
2526
"sigs.k8s.io/yaml"
2627
)
2728

2829
const teamsPutURLFormat = "/v0/organizations/%s/teams-bulk"
30+
const teamsGetURLFormat = "/v0/organizations/%s/teams"
2931

3032
type TeamInput struct {
33+
Name string `json:"name" yaml:"name"`
3134
Clusters []string `json:"clusters" yaml:"clusters"`
35+
Namespaces []string `json:"namespaces" yaml:"namespaces"`
36+
Repositories []string `json:"repositories" yaml:"repositories"`
3237
DisallowedClusters []string `json:"disallowedClusters" yaml:"disallowedClusters"`
3338
DisallowedNamespaces []string `json:"disallowedNamespaces" yaml:"disallowedNamespaces"`
3439
DisallowedRepositories []string `json:"disallowedRepositories" yaml:"disallowedRepositories"`
35-
Name string `json:"name" yaml:"name"`
36-
Namespaces []string `json:"namespaces" yaml:"namespaces"`
37-
Repositories []string `json:"repositories" yaml:"repositories"`
3840
AppGroups []string `json:"appGroups" yaml:"appGroups"`
3941
}
4042

43+
type TeamOutput = TeamInput
44+
4145
func PostTeams(client *req.Client, teamInput []TeamInput, deleteNonProvidedTeams bool, org string) error {
4246
url := fmt.Sprintf(teamsPutURLFormat, org)
4347
if deleteNonProvidedTeams {
@@ -53,38 +57,60 @@ func PostTeams(client *req.Client, teamInput []TeamInput, deleteNonProvidedTeams
5357
return nil
5458
}
5559

60+
func ListTeams(client *req.Client, org string) ([]TeamOutput, error) {
61+
url := fmt.Sprintf(teamsGetURLFormat, org)
62+
resp, err := client.R().SetHeaders(getHeaders()).Get(url)
63+
if err != nil {
64+
return nil, err
65+
}
66+
if resp.IsErrorState() {
67+
return nil, fmt.Errorf("invalid HTTP response %d %s", resp.StatusCode, string(resp.Bytes()))
68+
}
69+
teams := []TeamOutput{}
70+
err = resp.Unmarshal(&teams)
71+
if err != nil {
72+
return nil, fmt.Errorf("unable to convert response to json for teams: %w", err)
73+
}
74+
return teams, nil
75+
}
76+
5677
func PushTeams(client *req.Client, pushDir, org string, deleteNonProvidedTeams, dryRun bool) error {
5778
if pushDir == "" {
5879
return errors.New("pushDir cannot be empty")
5980
}
81+
6082
teamsFileName := pushDir + "/teams.yaml"
6183
logrus.Infof("Pushing teams configuration from %s", teamsFileName)
6284
_, err := os.Stat(teamsFileName)
6385
if err != nil {
6486
return err
6587
}
88+
6689
teamsFile, err := os.Open(teamsFileName)
6790
if err != nil {
6891
return err
6992
}
93+
7094
defer func() {
7195
if err := teamsFile.Close(); err != nil {
7296
logrus.Errorf("error closing teams file: %v", err)
7397
}
7498
}()
7599

76-
teams := []TeamInput{}
100+
localTeams := []TeamInput{}
77101
b, err := os.ReadFile(teamsFileName)
78102
if err != nil {
79103
return err
80104
}
81-
err = yaml.Unmarshal(b, &teams)
105+
106+
err = yaml.Unmarshal(b, &localTeams)
82107
if err != nil {
83108
return err
84109
}
110+
85111
if dryRun {
86112
logrus.Infof("Dry run: Would have pushed the following teams configuration:")
87-
for _, team := range teams {
113+
for _, team := range localTeams {
88114
logrus.Infof("Team: %s", team.Name)
89115
logrus.Infof(" Clusters: %v", team.Clusters)
90116
logrus.Infof(" Namespaces: %v", team.Namespaces)
@@ -94,12 +120,43 @@ func PushTeams(client *req.Client, pushDir, org string, deleteNonProvidedTeams,
94120
logrus.Infof(" DisallowedRepositories: %v", team.DisallowedRepositories)
95121
logrus.Infof(" AppGroups: %v", team.AppGroups)
96122
}
123+
124+
if deleteNonProvidedTeams {
125+
logrus.Infof("--------------------------------")
126+
127+
remoteTeams, err := ListTeams(client, org)
128+
if err != nil {
129+
return fmt.Errorf("error listing teams: %w", err)
130+
}
131+
remoteTeamsByName := lo.KeyBy(remoteTeams, func(i TeamOutput) string { return i.Name })
132+
localTeamsByName := lo.KeyBy(localTeams, func(i TeamInput) string { return i.Name })
133+
134+
teamsToBeDeleted := []string{}
135+
for name := range remoteTeamsByName {
136+
if _, ok := localTeamsByName[name]; !ok {
137+
teamsToBeDeleted = append(teamsToBeDeleted, name)
138+
}
139+
}
140+
141+
if len(teamsToBeDeleted) == 0 {
142+
logrus.Infof("Dry run: Would have deleted no teams")
143+
return nil
144+
}
145+
146+
logrus.Infof("Dry run: Would have deleted the following teams:")
147+
for _, team := range teamsToBeDeleted {
148+
logrus.Infof("Team: %s", team)
149+
}
150+
}
151+
97152
return nil
98153
}
99-
err = PostTeams(client, teams, deleteNonProvidedTeams, org)
154+
155+
err = PostTeams(client, localTeams, deleteNonProvidedTeams, org)
100156
if err != nil {
101157
return err
102158
}
159+
103160
logrus.Debugln("Done pushing teams configuration")
104161
return nil
105162
}

0 commit comments

Comments
 (0)