Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
96aac387c9 | ||
|
|
870f18c621 | ||
|
|
57b33e29f7 | ||
|
|
94b7917679 | ||
|
|
98fa0c4271 | ||
|
|
8282907bce | ||
|
|
323f4f5e5f | ||
|
|
744b3ebd0a | ||
|
|
3fdba35993 | ||
|
|
ebdf9ed379 | ||
|
|
a572274c5c | ||
|
|
6a6bba8669 | ||
|
|
1d1d4bbf4b | ||
|
|
d9bb4c631e | ||
|
|
722962c138 | ||
|
|
c98ff6ae87 | ||
|
|
cbef6a4cad | ||
|
|
f887a2c029 | ||
|
|
078cfe92c2 | ||
|
|
80ef184b60 | ||
|
|
f2475988bd | ||
|
|
45526108e0 | ||
|
|
414c0bbbdc | ||
|
|
6873a710d9 |
16
.github/workflows/bootstrap.yaml
vendored
16
.github/workflows/bootstrap.yaml
vendored
@@ -64,6 +64,22 @@ jobs:
|
||||
--team=team-z
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITPROVIDER_BOT_TOKEN }}
|
||||
- name: bootstrap customize
|
||||
run: |
|
||||
make setup-bootstrap-patch
|
||||
/tmp/flux bootstrap github --manifests ./manifests/install/ \
|
||||
--owner=fluxcd-testing \
|
||||
--repository=${{ steps.vars.outputs.test_repo_name }} \
|
||||
--branch=main \
|
||||
--path=test-cluster \
|
||||
--team=team-z
|
||||
if [ $(kubectl get deployments.apps source-controller -o jsonpath='{.spec.template.spec.securityContext.runAsUser}') != "10000" ]; then
|
||||
echo "Bootstrap not customized as controller is not running as user 10000" && exit 1
|
||||
fi
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITPROVIDER_BOT_TOKEN }}
|
||||
GITHUB_REPO_NAME: ${{ steps.vars.outputs.test_repo_name }}
|
||||
GITHUB_ORG_NAME: fluxcd-testing
|
||||
- name: libgit2
|
||||
run: |
|
||||
/tmp/flux create source git test-libgit2 \
|
||||
|
||||
7
.github/workflows/e2e.yaml
vendored
7
.github/workflows/e2e.yaml
vendored
@@ -191,7 +191,14 @@ jobs:
|
||||
/tmp/flux create kustomization flux-system \
|
||||
--source=flux-system \
|
||||
--path=./clusters/staging
|
||||
kubectl -n flux-system wait kustomization/infrastructure --for=condition=ready --timeout=5m
|
||||
kubectl -n flux-system wait kustomization/apps --for=condition=ready --timeout=5m
|
||||
kubectl -n nginx wait helmrelease/nginx --for=condition=ready --timeout=5m
|
||||
kubectl -n redis wait helmrelease/redis --for=condition=ready --timeout=5m
|
||||
kubectl -n podinfo wait helmrelease/podinfo --for=condition=ready --timeout=5m
|
||||
- name: flux tree
|
||||
run: |
|
||||
/tmp/flux tree kustomization flux-system | grep Service/podinfo
|
||||
- name: flux check
|
||||
run: |
|
||||
/tmp/flux check
|
||||
|
||||
@@ -30,7 +30,7 @@ you can sign your commit automatically with `git commit -s`.
|
||||
|
||||
For realtime communications we use Slack: To join the conversation, simply
|
||||
join the [CNCF](https://slack.cncf.io/) Slack workspace and use the
|
||||
[#flux-dev](https://cloud-native.slack.com/messages/flux-dev/) channel.
|
||||
[#flux-contributors](https://cloud-native.slack.com/messages/flux-contributors/) channel.
|
||||
|
||||
To discuss ideas and specifications we use [Github
|
||||
Discussions](https://github.com/fluxcd/flux2/discussions).
|
||||
|
||||
@@ -17,3 +17,4 @@ Hidde Beydals, Weaveworks <hidde@weave.works> (github: @hiddeco, slack: hidde)
|
||||
Max Jonas Werner, D2iQ <mwerner@d2iq.com> (github: @makkes, slack: max)
|
||||
Philip Laine, Xenit <philip.laine@xenit.se> (github: @phillebaba, slack: phillebaba)
|
||||
Stefan Prodan, Weaveworks <stefan@weave.works> (github: @stefanprodan, slack: stefanprodan)
|
||||
Sunny, Weaveworks <sunny@weave.works> (github: @darkowlzz, slack: darkowlzz)
|
||||
|
||||
4
Makefile
4
Makefile
@@ -58,10 +58,12 @@ install:
|
||||
install-dev:
|
||||
CGO_ENABLED=0 go build -o /usr/local/bin ./cmd/flux
|
||||
|
||||
|
||||
install-envtest: setup-envtest
|
||||
$(SETUP_ENVTEST) use $(ENVTEST_BIN_VERSION)
|
||||
|
||||
setup-bootstrap-patch:
|
||||
go run ./tests/bootstrap/main.go
|
||||
|
||||
# Find or download setup-envtest
|
||||
setup-envtest:
|
||||
ifeq (, $(shell which setup-envtest))
|
||||
|
||||
@@ -122,7 +122,7 @@ func (reconcile reconcileCommand) run(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
|
||||
if readyCond.Status != metav1.ConditionTrue {
|
||||
return fmt.Errorf("%s reconciliation failed: ''%s", reconcile.kind, readyCond.Message)
|
||||
return fmt.Errorf("%s reconciliation failed: '%s'", reconcile.kind, readyCond.Message)
|
||||
}
|
||||
logger.Successf(reconcile.object.successMessage())
|
||||
return nil
|
||||
|
||||
88
cmd/flux/testdata/tree/kustomizations.yaml
vendored
Normal file
88
cmd/flux/testdata/tree/kustomizations.yaml
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: {{ .fluxns }}
|
||||
---
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1beta2
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: flux-system
|
||||
namespace: {{ .fluxns }}
|
||||
spec:
|
||||
path: ./clusters/production
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: flux-system
|
||||
interval: 5m
|
||||
prune: true
|
||||
status:
|
||||
conditions:
|
||||
- lastTransitionTime: "2021-08-01T04:52:56Z"
|
||||
message: 'Applied revision: main/696f056df216eea4f9401adbee0ff744d4df390f'
|
||||
reason: ReconciliationSucceeded
|
||||
status: "True"
|
||||
type: Ready
|
||||
inventory:
|
||||
entries:
|
||||
- id: _{{ .fluxns }}__Namespace
|
||||
v: v1
|
||||
- id: {{ .fluxns }}_helm-controller_apps_Deployment
|
||||
v: v1
|
||||
- id: {{ .fluxns }}_kustomize-controller_apps_Deployment
|
||||
v: v1
|
||||
- id: {{ .fluxns }}_notification-controller_apps_Deployment
|
||||
v: v1
|
||||
- id: {{ .fluxns }}_source-controller_apps_Deployment
|
||||
v: v1
|
||||
- id: {{ .fluxns }}_infrastructure_kustomize.toolkit.fluxcd.io_Kustomization
|
||||
v: v1beta2
|
||||
- id: {{ .fluxns }}_flux-system_source.toolkit.fluxcd.io_GitRepository
|
||||
v: v1beta1
|
||||
---
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1beta2
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: infrastructure
|
||||
namespace: {{ .fluxns }}
|
||||
spec:
|
||||
path: ./infrastructure/production
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: flux-system
|
||||
interval: 5m
|
||||
prune: true
|
||||
status:
|
||||
conditions:
|
||||
- lastTransitionTime: "2021-08-01T04:52:56Z"
|
||||
message: 'Applied revision: main/696f056df216eea4f9401adbee0ff744d4df390f'
|
||||
reason: ReconciliationSucceeded
|
||||
status: "True"
|
||||
type: Ready
|
||||
inventory:
|
||||
entries:
|
||||
- id: _cert-manager__Namespace
|
||||
v: v1
|
||||
- id: cert-manager_cert-manager_source.toolkit.fluxcd.io_HelmRepository
|
||||
v: v1beta1
|
||||
---
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1beta2
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: empty
|
||||
namespace: {{ .fluxns }}
|
||||
spec:
|
||||
path: ./apps/todo
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: flux-system
|
||||
interval: 5m
|
||||
prune: true
|
||||
status:
|
||||
conditions:
|
||||
- lastTransitionTime: "2021-08-01T04:52:56Z"
|
||||
message: 'Applied revision: main/696f056df216eea4f9401adbee0ff744d4df390f'
|
||||
reason: ReconciliationSucceeded
|
||||
status: "True"
|
||||
type: Ready
|
||||
---
|
||||
5
cmd/flux/testdata/tree/tree-compact.golden
vendored
Normal file
5
cmd/flux/testdata/tree/tree-compact.golden
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
Kustomization/{{ .fluxns }}/flux-system
|
||||
├── Kustomization/{{ .fluxns }}/infrastructure
|
||||
│ └── HelmRepository/cert-manager/cert-manager
|
||||
└── GitRepository/{{ .fluxns }}/flux-system
|
||||
|
||||
2
cmd/flux/testdata/tree/tree-empty.golden
vendored
Normal file
2
cmd/flux/testdata/tree/tree-empty.golden
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
Kustomization/{{ .fluxns }}/empty
|
||||
|
||||
11
cmd/flux/testdata/tree/tree.golden
vendored
Normal file
11
cmd/flux/testdata/tree/tree.golden
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
Kustomization/{{ .fluxns }}/flux-system
|
||||
├── Namespace/{{ .fluxns }}
|
||||
├── Deployment/{{ .fluxns }}/helm-controller
|
||||
├── Deployment/{{ .fluxns }}/kustomize-controller
|
||||
├── Deployment/{{ .fluxns }}/notification-controller
|
||||
├── Deployment/{{ .fluxns }}/source-controller
|
||||
├── Kustomization/{{ .fluxns }}/infrastructure
|
||||
│ ├── Namespace/cert-manager
|
||||
│ └── HelmRepository/cert-manager/cert-manager
|
||||
└── GitRepository/{{ .fluxns }}/flux-system
|
||||
|
||||
31
cmd/flux/tree.go
Normal file
31
cmd/flux/tree.go
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
Copyright 2021 The Flux authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var treeCmd = &cobra.Command{
|
||||
Use: "tree",
|
||||
Short: "Print the resources reconciled by Flux",
|
||||
Long: `The tree command shows the list of resources reconciled by a Flux object.'`,
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(treeCmd)
|
||||
}
|
||||
269
cmd/flux/tree_kustomization.go
Normal file
269
cmd/flux/tree_kustomization.go
Normal file
@@ -0,0 +1,269 @@
|
||||
/*
|
||||
Copyright 2021 The Flux authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
|
||||
"github.com/fluxcd/flux2/internal/tree"
|
||||
"github.com/fluxcd/flux2/internal/utils"
|
||||
helmv2 "github.com/fluxcd/helm-controller/api/v2beta1"
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2"
|
||||
"github.com/fluxcd/pkg/ssa"
|
||||
"github.com/spf13/cobra"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"sigs.k8s.io/cli-utils/pkg/object"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/yaml"
|
||||
)
|
||||
|
||||
var treeKsCmd = &cobra.Command{
|
||||
Use: "kustomization [name]",
|
||||
Aliases: []string{"ks", "kustomization"},
|
||||
Short: "Print the resource inventory of a Kustomization",
|
||||
Long: `The tree command prints the resource list reconciled by a Kustomization.'`,
|
||||
Example: ` # Print the resources managed by the root Kustomization
|
||||
flux tree kustomization flux-system
|
||||
|
||||
# Print the Flux resources managed by the root Kustomization
|
||||
flux tree kustomization flux-system --compact`,
|
||||
RunE: treeKsCmdRun,
|
||||
}
|
||||
|
||||
type TreeKsFlags struct {
|
||||
compact bool
|
||||
output string
|
||||
}
|
||||
|
||||
var treeKsArgs TreeKsFlags
|
||||
|
||||
func init() {
|
||||
treeKsCmd.Flags().BoolVar(&treeKsArgs.compact, "compact", false, "list Flux resources only.")
|
||||
treeKsCmd.Flags().StringVarP(&treeKsArgs.output, "output", "o", "",
|
||||
"the format in which the tree should be printed. can be 'json' or 'yaml'")
|
||||
treeCmd.AddCommand(treeKsCmd)
|
||||
}
|
||||
|
||||
func treeKsCmdRun(cmd *cobra.Command, args []string) error {
|
||||
if len(args) < 1 {
|
||||
return fmt.Errorf("kustomization name is required")
|
||||
}
|
||||
name := args[0]
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
|
||||
defer cancel()
|
||||
|
||||
kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
k := &kustomizev1.Kustomization{}
|
||||
err = kubeClient.Get(ctx, client.ObjectKey{
|
||||
Namespace: rootArgs.namespace,
|
||||
Name: name,
|
||||
}, k)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
kMeta, err := object.CreateObjMetadata(k.Namespace, k.Name,
|
||||
schema.GroupKind{Group: kustomizev1.GroupVersion.Group, Kind: kustomizev1.KustomizationKind})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
kTree := tree.New(kMeta)
|
||||
err = treeKustomization(ctx, kTree, k, kubeClient, treeKsArgs.compact)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch treeKsArgs.output {
|
||||
case "json":
|
||||
data, err := json.MarshalIndent(kTree, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rootCmd.Println(string(data))
|
||||
case "yaml":
|
||||
data, err := yaml.Marshal(kTree)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rootCmd.Println(string(data))
|
||||
default:
|
||||
rootCmd.Println(kTree.Print())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func treeKustomization(ctx context.Context, tree tree.ObjMetadataTree, item *kustomizev1.Kustomization, kubeClient client.Client, compact bool) error {
|
||||
if item.Status.Inventory == nil || len(item.Status.Inventory.Entries) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
compactGroup := "toolkit.fluxcd.io"
|
||||
|
||||
for _, entry := range item.Status.Inventory.Entries {
|
||||
objMetadata, err := object.ParseObjMetadata(entry.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if compact && !strings.Contains(objMetadata.GroupKind.Group, compactGroup) {
|
||||
continue
|
||||
}
|
||||
|
||||
if objMetadata.GroupKind.Group == kustomizev1.GroupVersion.Group &&
|
||||
objMetadata.GroupKind.Kind == kustomizev1.KustomizationKind &&
|
||||
objMetadata.Namespace == item.Namespace &&
|
||||
objMetadata.Name == item.Name {
|
||||
continue
|
||||
}
|
||||
|
||||
ks := tree.Add(objMetadata)
|
||||
|
||||
if objMetadata.GroupKind.Group == helmv2.GroupVersion.Group &&
|
||||
objMetadata.GroupKind.Kind == helmv2.HelmReleaseKind {
|
||||
objects, err := getHelmReleaseInventory(
|
||||
ctx, client.ObjectKey{
|
||||
Namespace: objMetadata.Namespace,
|
||||
Name: objMetadata.Name,
|
||||
}, kubeClient)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, obj := range objects {
|
||||
if compact && !strings.Contains(obj.GroupKind.Group, compactGroup) {
|
||||
continue
|
||||
}
|
||||
ks.Add(obj)
|
||||
}
|
||||
}
|
||||
|
||||
if objMetadata.GroupKind.Group == kustomizev1.GroupVersion.Group &&
|
||||
objMetadata.GroupKind.Kind == kustomizev1.KustomizationKind {
|
||||
k := &kustomizev1.Kustomization{}
|
||||
err = kubeClient.Get(ctx, client.ObjectKey{
|
||||
Namespace: objMetadata.Namespace,
|
||||
Name: objMetadata.Name,
|
||||
}, k)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to find object: %w", err)
|
||||
}
|
||||
err := treeKustomization(ctx, ks, k, kubeClient, compact)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type hrStorage struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
Manifest string `json:"manifest,omitempty"`
|
||||
}
|
||||
|
||||
func getHelmReleaseInventory(ctx context.Context, objectKey client.ObjectKey, kubeClient client.Client) ([]object.ObjMetadata, error) {
|
||||
hr := &helmv2.HelmRelease{}
|
||||
if err := kubeClient.Get(ctx, objectKey, hr); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
storageNamespace := hr.GetNamespace()
|
||||
if hr.Spec.StorageNamespace != "" {
|
||||
storageNamespace = hr.Spec.StorageNamespace
|
||||
}
|
||||
|
||||
storageName := hr.GetName()
|
||||
if hr.Spec.ReleaseName != "" {
|
||||
storageName = hr.Spec.ReleaseName
|
||||
} else if hr.Spec.TargetNamespace != "" {
|
||||
storageName = strings.Join([]string{hr.Spec.TargetNamespace, hr.Name}, "-")
|
||||
}
|
||||
|
||||
storageVersion := hr.Status.LastReleaseRevision
|
||||
// skip release if it failed to install
|
||||
if storageVersion < 1 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
storageKey := client.ObjectKey{
|
||||
Namespace: storageNamespace,
|
||||
Name: fmt.Sprintf("sh.helm.release.v1.%s.v%v", storageName, storageVersion),
|
||||
}
|
||||
|
||||
storageSecret := &corev1.Secret{}
|
||||
if err := kubeClient.Get(ctx, storageKey, storageSecret); err != nil {
|
||||
// skip release if it has no storage
|
||||
if apierrors.IsNotFound(err) {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, fmt.Errorf("failed to find the Helm storage object for HelmRelease '%s': %w", objectKey.String(), err)
|
||||
}
|
||||
|
||||
releaseData, releaseFound := storageSecret.Data["release"]
|
||||
if !releaseFound {
|
||||
return nil, fmt.Errorf("failed to decode the Helm storage object for HelmRelease '%s'", objectKey.String())
|
||||
}
|
||||
|
||||
// adapted from https://github.com/helm/helm/blob/02685e94bd3862afcb44f6cd7716dbeb69743567/pkg/storage/driver/util.go
|
||||
var b64 = base64.StdEncoding
|
||||
b, err := b64.DecodeString(string(releaseData))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var magicGzip = []byte{0x1f, 0x8b, 0x08}
|
||||
if bytes.Equal(b[0:3], magicGzip) {
|
||||
r, err := gzip.NewReader(bytes.NewReader(b))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer r.Close()
|
||||
b2, err := ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b = b2
|
||||
}
|
||||
|
||||
var rls hrStorage
|
||||
if err := json.Unmarshal(b, &rls); err != nil {
|
||||
return nil, fmt.Errorf("failed to decode the Helm storage object for HelmRelease '%s': %w", objectKey.String(), err)
|
||||
}
|
||||
|
||||
objects, err := ssa.ReadObjects(strings.NewReader(rls.Manifest))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read the Helm storage object for HelmRelease '%s': %w", objectKey.String(), err)
|
||||
}
|
||||
|
||||
return object.UnstructuredsToObjMetas(objects)
|
||||
}
|
||||
64
cmd/flux/tree_kustomization_test.go
Normal file
64
cmd/flux/tree_kustomization_test.go
Normal file
@@ -0,0 +1,64 @@
|
||||
// +build unit
|
||||
|
||||
/*
|
||||
Copyright 2021 The Flux authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestTree(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
args string
|
||||
objectFile string
|
||||
goldenFile string
|
||||
}{
|
||||
{
|
||||
"tree kustomization",
|
||||
"tree kustomization flux-system",
|
||||
"testdata/tree/kustomizations.yaml",
|
||||
"testdata/tree/tree.golden",
|
||||
},
|
||||
{
|
||||
"tree kustomization compact",
|
||||
"tree kustomization flux-system --compact",
|
||||
"testdata/tree/kustomizations.yaml",
|
||||
"testdata/tree/tree-compact.golden",
|
||||
},
|
||||
{
|
||||
"tree kustomization empty",
|
||||
"tree kustomization empty",
|
||||
"testdata/tree/kustomizations.yaml",
|
||||
"testdata/tree/tree-empty.golden",
|
||||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
tmpl := map[string]string{
|
||||
"fluxns": allocateNamespace("flux-system"),
|
||||
}
|
||||
testEnv.CreateObjectFile(tc.objectFile, tmpl, t)
|
||||
cmd := cmdTestCase{
|
||||
args: tc.args + " -n=" + tmpl["fluxns"],
|
||||
assert: assertGoldenTemplateFile(tc.goldenFile, tmpl),
|
||||
}
|
||||
cmd.runTestCmd(t)
|
||||
})
|
||||
}
|
||||
}
|
||||
4
go.mod
4
go.mod
@@ -8,7 +8,7 @@ require (
|
||||
github.com/cyphar/filepath-securejoin v0.2.2
|
||||
github.com/fluxcd/go-git-providers v0.1.1
|
||||
github.com/fluxcd/helm-controller/api v0.12.1
|
||||
github.com/fluxcd/image-automation-controller/api v0.15.0
|
||||
github.com/fluxcd/image-automation-controller/api v0.16.0
|
||||
github.com/fluxcd/image-reflector-controller/api v0.13.0
|
||||
github.com/fluxcd/kustomize-controller/api v0.16.0
|
||||
github.com/fluxcd/notification-controller/api v0.18.1
|
||||
@@ -18,7 +18,7 @@ require (
|
||||
github.com/fluxcd/pkg/ssh v0.0.5
|
||||
github.com/fluxcd/pkg/untar v0.0.5
|
||||
github.com/fluxcd/pkg/version v0.0.1
|
||||
github.com/fluxcd/source-controller/api v0.16.1
|
||||
github.com/fluxcd/source-controller/api v0.17.1
|
||||
github.com/go-errors/errors v1.4.0 // indirect
|
||||
github.com/go-git/go-git/v5 v5.4.2
|
||||
github.com/google/go-cmp v0.5.6
|
||||
|
||||
10
go.sum
10
go.sum
@@ -227,8 +227,8 @@ github.com/fluxcd/go-git-providers v0.1.1 h1:R4VafMOo1IlfEZcImApCeElge/HajhFvRzD
|
||||
github.com/fluxcd/go-git-providers v0.1.1/go.mod h1:nRgNpHZmZhrsyNSma1JcAhjUG9xrqMGJcIUr9K7M7vk=
|
||||
github.com/fluxcd/helm-controller/api v0.12.1 h1:rDyhMPvbhCxslqiNNG4nlfDCeYgrk6D+1ZKLsBS/Irs=
|
||||
github.com/fluxcd/helm-controller/api v0.12.1/go.mod h1:zWmzV0s2SU4rEIGLPTt+dsaMs40OsNQgSgOATgJmxB0=
|
||||
github.com/fluxcd/image-automation-controller/api v0.15.0 h1:KI350vt5JahE43D17VyLZFH4ZxtbnyHrekAd8AJsT5E=
|
||||
github.com/fluxcd/image-automation-controller/api v0.15.0/go.mod h1:XvrEEpM1rVU+x1gQeXB/dj56w1dmOJRraTxQWOiuNME=
|
||||
github.com/fluxcd/image-automation-controller/api v0.16.0 h1:pPvEdb8Q7LgNVfugF3+/z2JQdUZ4ecYWrXiezLPov0w=
|
||||
github.com/fluxcd/image-automation-controller/api v0.16.0/go.mod h1:tEQCFKGgxii7zfXti2MxixwFbxhEXnVJqLGM2x9zlGw=
|
||||
github.com/fluxcd/image-reflector-controller/api v0.13.0 h1:5kq0Jqh+ndZIye+4csfEbuos5GaXIiK77Gpx+ojo+f8=
|
||||
github.com/fluxcd/image-reflector-controller/api v0.13.0/go.mod h1:lgQHGFz29OHmDU5Jwg689C/M+P/f9ujt6NS0zCLT0BQ=
|
||||
github.com/fluxcd/kustomize-controller/api v0.16.0 h1:L/LRxS6oroGZe1AdElP3k1mnNIKGCpi0ntgHwJzdNYY=
|
||||
@@ -250,9 +250,9 @@ github.com/fluxcd/pkg/untar v0.0.5 h1:UGI3Ch1UIEIaqQvMicmImL1s9npQa64DJ/ozqHKB7g
|
||||
github.com/fluxcd/pkg/untar v0.0.5/go.mod h1:O6V9+rtl8c1mHBafgqFlJN6zkF1HS5SSYn7RpQJ/nfw=
|
||||
github.com/fluxcd/pkg/version v0.0.1 h1:/8asQoDXSThz3csiwi4Qo8Zb6blAxLXbtxNgeMJ9bCg=
|
||||
github.com/fluxcd/pkg/version v0.0.1/go.mod h1:WAF4FEEA9xyhngF8TDxg3UPu5fA1qhEYV8Pmi2Il01Q=
|
||||
github.com/fluxcd/source-controller/api v0.16.0/go.mod h1:guUCCapjzE2kocwFreQTM/IGvtAglIJc4L97mokairo=
|
||||
github.com/fluxcd/source-controller/api v0.16.1 h1:3K0OueH0UA4iwIjKAXS72NaPBMO9OFx0xnB5S2am/AM=
|
||||
github.com/fluxcd/source-controller/api v0.16.1/go.mod h1:guUCCapjzE2kocwFreQTM/IGvtAglIJc4L97mokairo=
|
||||
github.com/fluxcd/source-controller/api v0.17.0/go.mod h1:guUCCapjzE2kocwFreQTM/IGvtAglIJc4L97mokairo=
|
||||
github.com/fluxcd/source-controller/api v0.17.1 h1:bsYMc/6U2sYXLfxcZtDavsqUYGDHFycqVEAEGW3NiPs=
|
||||
github.com/fluxcd/source-controller/api v0.17.1/go.mod h1:guUCCapjzE2kocwFreQTM/IGvtAglIJc4L97mokairo=
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
||||
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
|
||||
github.com/form3tech-oss/jwt-go v3.2.3+incompatible h1:7ZaBxOI7TMoYBfyA3cQHErNNyAWIKUMIwqxEtgHOs5c=
|
||||
|
||||
141
internal/tree/tree.go
Normal file
141
internal/tree/tree.go
Normal file
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
Copyright 2021 The Flux authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
Derived work from https://github.com/d6o/GoTree
|
||||
Copyright (c) 2017 Diego Siqueira
|
||||
*/
|
||||
|
||||
package tree
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/fluxcd/pkg/ssa"
|
||||
"sigs.k8s.io/cli-utils/pkg/object"
|
||||
)
|
||||
|
||||
const (
|
||||
newLine = "\n"
|
||||
emptySpace = " "
|
||||
middleItem = "├── "
|
||||
continueItem = "│ "
|
||||
lastItem = "└── "
|
||||
)
|
||||
|
||||
type (
|
||||
objMetadataTree struct {
|
||||
Resource object.ObjMetadata `json:"resource"`
|
||||
ResourceTree []ObjMetadataTree `json:"resources,omitempty"`
|
||||
}
|
||||
|
||||
ObjMetadataTree interface {
|
||||
Add(objMetadata object.ObjMetadata) ObjMetadataTree
|
||||
AddTree(tree ObjMetadataTree)
|
||||
Items() []ObjMetadataTree
|
||||
Text() string
|
||||
Print() string
|
||||
}
|
||||
|
||||
printer struct {
|
||||
}
|
||||
|
||||
Printer interface {
|
||||
Print(ObjMetadataTree) string
|
||||
}
|
||||
)
|
||||
|
||||
func New(objMetadata object.ObjMetadata) ObjMetadataTree {
|
||||
return &objMetadataTree{
|
||||
Resource: objMetadata,
|
||||
ResourceTree: []ObjMetadataTree{},
|
||||
}
|
||||
}
|
||||
|
||||
func (t *objMetadataTree) Add(objMetadata object.ObjMetadata) ObjMetadataTree {
|
||||
n := New(objMetadata)
|
||||
t.ResourceTree = append(t.ResourceTree, n)
|
||||
return n
|
||||
}
|
||||
|
||||
func (t *objMetadataTree) AddTree(tree ObjMetadataTree) {
|
||||
t.ResourceTree = append(t.ResourceTree, tree)
|
||||
}
|
||||
|
||||
func (t *objMetadataTree) Text() string {
|
||||
return ssa.FmtObjMetadata(t.Resource)
|
||||
}
|
||||
|
||||
func (t *objMetadataTree) Items() []ObjMetadataTree {
|
||||
return t.ResourceTree
|
||||
}
|
||||
|
||||
func (t *objMetadataTree) Print() string {
|
||||
return newPrinter().Print(t)
|
||||
}
|
||||
|
||||
func newPrinter() Printer {
|
||||
return &printer{}
|
||||
}
|
||||
|
||||
func (p *printer) Print(t ObjMetadataTree) string {
|
||||
return t.Text() + newLine + p.printItems(t.Items(), []bool{})
|
||||
}
|
||||
|
||||
func (p *printer) printText(text string, spaces []bool, last bool) string {
|
||||
var result string
|
||||
for _, space := range spaces {
|
||||
if space {
|
||||
result += emptySpace
|
||||
} else {
|
||||
result += continueItem
|
||||
}
|
||||
}
|
||||
|
||||
indicator := middleItem
|
||||
if last {
|
||||
indicator = lastItem
|
||||
}
|
||||
|
||||
var out string
|
||||
lines := strings.Split(text, "\n")
|
||||
for i := range lines {
|
||||
text := lines[i]
|
||||
if i == 0 {
|
||||
out += result + indicator + text + newLine
|
||||
continue
|
||||
}
|
||||
if last {
|
||||
indicator = emptySpace
|
||||
} else {
|
||||
indicator = continueItem
|
||||
}
|
||||
out += result + indicator + text + newLine
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
func (p *printer) printItems(t []ObjMetadataTree, spaces []bool) string {
|
||||
var result string
|
||||
for i, f := range t {
|
||||
last := i == len(t)-1
|
||||
result += p.printText(f.Text(), spaces, last)
|
||||
if len(f.Items()) > 0 {
|
||||
spacesChild := append(spaces, last)
|
||||
result += p.printItems(f.Items(), spacesChild)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- https://github.com/fluxcd/image-automation-controller/releases/download/v0.15.0/image-automation-controller.crds.yaml
|
||||
- https://github.com/fluxcd/image-automation-controller/releases/download/v0.15.0/image-automation-controller.deployment.yaml
|
||||
- https://github.com/fluxcd/image-automation-controller/releases/download/v0.16.0/image-automation-controller.crds.yaml
|
||||
- https://github.com/fluxcd/image-automation-controller/releases/download/v0.16.0/image-automation-controller.deployment.yaml
|
||||
- account.yaml
|
||||
patchesJson6902:
|
||||
- target:
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- https://github.com/fluxcd/source-controller/releases/download/v0.16.1/source-controller.crds.yaml
|
||||
- https://github.com/fluxcd/source-controller/releases/download/v0.16.1/source-controller.deployment.yaml
|
||||
- https://github.com/fluxcd/source-controller/releases/download/v0.17.1/source-controller.crds.yaml
|
||||
- https://github.com/fluxcd/source-controller/releases/download/v0.17.1/source-controller.deployment.yaml
|
||||
- account.yaml
|
||||
patchesJson6902:
|
||||
- target:
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- https://github.com/fluxcd/source-controller/releases/download/v0.16.1/source-controller.crds.yaml
|
||||
- https://github.com/fluxcd/source-controller/releases/download/v0.17.1/source-controller.crds.yaml
|
||||
- https://github.com/fluxcd/kustomize-controller/releases/download/v0.16.0/kustomize-controller.crds.yaml
|
||||
- https://github.com/fluxcd/helm-controller/releases/download/v0.12.1/helm-controller.crds.yaml
|
||||
- https://github.com/fluxcd/notification-controller/releases/download/v0.18.1/notification-controller.crds.yaml
|
||||
- https://github.com/fluxcd/image-reflector-controller/releases/download/v0.13.0/image-reflector-controller.crds.yaml
|
||||
- https://github.com/fluxcd/image-automation-controller/releases/download/v0.15.0/image-automation-controller.crds.yaml
|
||||
- https://github.com/fluxcd/image-automation-controller/releases/download/v0.16.0/image-automation-controller.crds.yaml
|
||||
|
||||
@@ -5,13 +5,13 @@ go 1.16
|
||||
require (
|
||||
github.com/Azure/azure-event-hubs-go/v3 v3.3.13
|
||||
github.com/fluxcd/helm-controller/api v0.12.1
|
||||
github.com/fluxcd/image-automation-controller/api v0.15.0
|
||||
github.com/fluxcd/image-automation-controller/api v0.16.0
|
||||
github.com/fluxcd/image-reflector-controller/api v0.13.0
|
||||
github.com/fluxcd/kustomize-controller/api v0.16.0
|
||||
github.com/fluxcd/notification-controller/api v0.18.1
|
||||
github.com/fluxcd/pkg/apis/meta v0.10.1
|
||||
github.com/fluxcd/pkg/runtime v0.12.1
|
||||
github.com/fluxcd/source-controller/api v0.16.1
|
||||
github.com/fluxcd/source-controller/api v0.17.0
|
||||
github.com/hashicorp/terraform-exec v0.14.0
|
||||
github.com/libgit2/git2go/v31 v31.6.1
|
||||
github.com/microsoft/azure-devops-go-api/azuredevops v1.0.0-b5
|
||||
|
||||
@@ -193,8 +193,8 @@ github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5Kwzbycv
|
||||
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/fluxcd/helm-controller/api v0.12.1 h1:rDyhMPvbhCxslqiNNG4nlfDCeYgrk6D+1ZKLsBS/Irs=
|
||||
github.com/fluxcd/helm-controller/api v0.12.1/go.mod h1:zWmzV0s2SU4rEIGLPTt+dsaMs40OsNQgSgOATgJmxB0=
|
||||
github.com/fluxcd/image-automation-controller/api v0.15.0 h1:KI350vt5JahE43D17VyLZFH4ZxtbnyHrekAd8AJsT5E=
|
||||
github.com/fluxcd/image-automation-controller/api v0.15.0/go.mod h1:XvrEEpM1rVU+x1gQeXB/dj56w1dmOJRraTxQWOiuNME=
|
||||
github.com/fluxcd/image-automation-controller/api v0.16.0 h1:pPvEdb8Q7LgNVfugF3+/z2JQdUZ4ecYWrXiezLPov0w=
|
||||
github.com/fluxcd/image-automation-controller/api v0.16.0/go.mod h1:tEQCFKGgxii7zfXti2MxixwFbxhEXnVJqLGM2x9zlGw=
|
||||
github.com/fluxcd/image-reflector-controller/api v0.13.0 h1:5kq0Jqh+ndZIye+4csfEbuos5GaXIiK77Gpx+ojo+f8=
|
||||
github.com/fluxcd/image-reflector-controller/api v0.13.0/go.mod h1:lgQHGFz29OHmDU5Jwg689C/M+P/f9ujt6NS0zCLT0BQ=
|
||||
github.com/fluxcd/kustomize-controller/api v0.16.0 h1:L/LRxS6oroGZe1AdElP3k1mnNIKGCpi0ntgHwJzdNYY=
|
||||
@@ -210,9 +210,8 @@ github.com/fluxcd/pkg/apis/meta v0.10.1/go.mod h1:yUblM2vg+X8TE3A2VvJfdhkGmg+uqB
|
||||
github.com/fluxcd/pkg/runtime v0.12.0/go.mod h1:EyaTR2TOYcjL5U//C4yH3bt2tvTgIOSXpVRbWxUn/C4=
|
||||
github.com/fluxcd/pkg/runtime v0.12.1 h1:r0KQG80gKY1NMp62FggSEdFBV60ZfbnA2RHL9y06DOY=
|
||||
github.com/fluxcd/pkg/runtime v0.12.1/go.mod h1:9czAjokV0w22eYGR9/SQKUHXhvh7ISNVgc/6a6YMBE8=
|
||||
github.com/fluxcd/source-controller/api v0.16.0/go.mod h1:guUCCapjzE2kocwFreQTM/IGvtAglIJc4L97mokairo=
|
||||
github.com/fluxcd/source-controller/api v0.16.1 h1:3K0OueH0UA4iwIjKAXS72NaPBMO9OFx0xnB5S2am/AM=
|
||||
github.com/fluxcd/source-controller/api v0.16.1/go.mod h1:guUCCapjzE2kocwFreQTM/IGvtAglIJc4L97mokairo=
|
||||
github.com/fluxcd/source-controller/api v0.17.0 h1:skXx2H5SeziUTwJrp9MPJNwTtYTctJMQ7ZIJfLmg9b0=
|
||||
github.com/fluxcd/source-controller/api v0.17.0/go.mod h1:guUCCapjzE2kocwFreQTM/IGvtAglIJc4L97mokairo=
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
||||
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
|
||||
github.com/form3tech-oss/jwt-go v3.2.3+incompatible h1:7ZaBxOI7TMoYBfyA3cQHErNNyAWIKUMIwqxEtgHOs5c=
|
||||
|
||||
@@ -19,7 +19,6 @@ package test
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
@@ -49,7 +48,7 @@ const defaultBranch = "main"
|
||||
|
||||
// getKubernetesCredentials returns a path to a kubeconfig file and a kube client instance.
|
||||
func getKubernetesCredentials(kubeconfig, aksHost, aksCert, aksKey, aksCa string) (string, client.Client, error) {
|
||||
tmpDir, err := ioutil.TempDir("", "*-azure-e2e")
|
||||
tmpDir, err := os.MkdirTemp("", "*-azure-e2e")
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
@@ -309,7 +308,7 @@ func getRepository(url, branchName string, overrideBranch bool, password string)
|
||||
checkoutBranch = branchName
|
||||
}
|
||||
|
||||
tmpDir, err := ioutil.TempDir("", "*-repository")
|
||||
tmpDir, err := os.MkdirTemp("", "*-repository")
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
99
tests/bootstrap/main.go
Normal file
99
tests/bootstrap/main.go
Normal file
@@ -0,0 +1,99 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/fluxcd/go-git-providers/github"
|
||||
"github.com/fluxcd/go-git-providers/gitprovider"
|
||||
"k8s.io/client-go/util/retry"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ks := "test-cluster/flux-system/kustomization.yaml"
|
||||
patchName := "test-cluster/flux-system/gotk-patches.yaml"
|
||||
ksContent := `apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- gotk-components.yaml
|
||||
- gotk-sync.yaml
|
||||
patches:
|
||||
- path: gotk-patches.yaml
|
||||
target:
|
||||
kind: Deployment`
|
||||
patchContent := `apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: all-flux-components
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
# Required by Kubernetes node autoscaler
|
||||
cluster-autoscaler.kubernetes.io/safe-to-evict: "true"
|
||||
spec:
|
||||
securityContext:
|
||||
runAsUser: 10000
|
||||
fsGroup: 1337
|
||||
containers:
|
||||
- name: manager
|
||||
securityContext:
|
||||
readOnlyRootFilesystem: true
|
||||
allowPrivilegeEscalation: false
|
||||
runAsNonRoot: true
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
`
|
||||
commitFiles := []gitprovider.CommitFile{
|
||||
{
|
||||
Path: &ks,
|
||||
Content: &ksContent,
|
||||
},
|
||||
{
|
||||
Path: &patchName,
|
||||
Content: &patchContent,
|
||||
},
|
||||
}
|
||||
|
||||
orgName := os.Getenv("GITHUB_ORG_NAME")
|
||||
repoName := os.Getenv("GITHUB_REPO_NAME")
|
||||
githubToken := os.Getenv(github.TokenVariable)
|
||||
client, err := github.NewClient(github.WithOAuth2Token(githubToken))
|
||||
if err != nil {
|
||||
log.Fatalf("error initializing github client: %s", err)
|
||||
}
|
||||
|
||||
repoRef := gitprovider.OrgRepositoryRef{
|
||||
OrganizationRef: gitprovider.OrganizationRef{
|
||||
Organization: orgName,
|
||||
Domain: github.DefaultDomain,
|
||||
},
|
||||
RepositoryName: repoName,
|
||||
}
|
||||
|
||||
if ok, err := client.HasTokenPermission(context.Background(), gitprovider.TokenPermissionRWRepository); err != nil {
|
||||
log.Fatalf("error getting token permission: %s", err)
|
||||
} else {
|
||||
if !ok {
|
||||
log.Fatal("token has no write permissions")
|
||||
}
|
||||
}
|
||||
|
||||
var repo gitprovider.OrgRepository
|
||||
err = retry.OnError(retry.DefaultRetry, func(err error) bool {
|
||||
return err != nil
|
||||
}, func() error {
|
||||
repo, err = client.OrgRepositories().Get(context.Background(), repoRef)
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalf("error getting %s repository in org %s: %s", repoRef.RepositoryName, repoRef.Organization, err)
|
||||
}
|
||||
|
||||
_, err = repo.Commits().Create(context.Background(), "main", "add patch manifest 3", commitFiles)
|
||||
if err != nil {
|
||||
log.Fatalf("error making commit: %s", err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user