File kubectl-dup-0.3.2.obscpio of Package kubectl-dup

07070100000000000041ED00000000000000000000000266C10ABB00000000000000000000000000000000000000000000001A00000000kubectl-dup-0.3.2/.github07070100000001000041ED00000000000000000000000266C10ABB00000000000000000000000000000000000000000000002400000000kubectl-dup-0.3.2/.github/workflows07070100000002000081A400000000000000000000000166C10ABB0000023B000000000000000000000000000000000000003000000000kubectl-dup-0.3.2/.github/workflows/release.ymlname: release
on:
  push:
    tags:
      - 'v*.*.*'
jobs:
  goreleaser:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@master
      - name: Setup Go
        uses: actions/setup-go@v5
      - name: GoReleaser
        uses: goreleaser/goreleaser-action@v6
        with:
          distribution: goreleaser
          version: '~> v2'
          args: release --clean
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      - name: Update new version in krew-index
        uses: rajatjindal/krew-release-bot@v0.0.46
07070100000003000081A400000000000000000000000166C10ABB000001ED000000000000000000000000000000000000001D00000000kubectl-dup-0.3.2/.gitignore# If you prefer the allow list template instead of the deny list, see community template:
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
#
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
/bin/*
/dist/*

# Test binary, built with `go test -c`
*.test

# Output of the go coverage tool, specifically when used with LiteIDE
*.out

# Dependency directories (remove the comment below to include it)
# vendor/

# Go workspace file
go.work
07070100000004000081A400000000000000000000000166C10ABB000002E8000000000000000000000000000000000000002200000000kubectl-dup-0.3.2/.goreleaser.ymlversion: 2

before:
  hooks:
    - go mod tidy

builds:
  - env:
      - CGO_ENABLED=0
    goos:
      - linux
      - darwin
      - windows
    goarch:
      - amd64
      - arm64
    ignore:
      - goos: windows
        goarch: arm64
    mod_timestamp: "{{ .CommitTimestamp }}"
    binary: kubectl-dup
    ldflags:
      - -s -w

checksum:
  name_template: "{{ .ProjectName }}_{{ .Tag }}_checksums.txt"

archives:
  - format: tar.gz
    name_template: "{{ .ProjectName }}_{{ .Tag }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}"
    # use zip for windows archives
    format_overrides:
      - goos: windows
        format: zip

changelog:
  use: github

snapshot:
  version_template: "{{ incminor .Tag }}-dev-{{ .ShortCommit }}"
07070100000005000081A400000000000000000000000166C10ABB00000624000000000000000000000000000000000000001D00000000kubectl-dup-0.3.2/.krew.yamlapiVersion: krew.googlecontainertools.github.com/v1alpha2
kind: Plugin
metadata:
  name: dup
spec:
  version: {{ .TagName }}
  homepage: https://github.com/vash/dup
  shortDescription: Duplicate existing Kubernetes resources
  description: |
    This plugin is designed for on-the-fly duplication of Kubernetes resources.
    It focuses on providing a convenient way to edit resources before duplication,
    with a specific emphasis on Pods to create a fine-tuned resource quickly.
    This tool can be used for debugging running containers without them crashing,
    and simplifying the administration and general interaction with Kubernetes clusters.
  platforms:
  - selector:
      matchLabels:
        os: darwin
        arch: amd64
    {{addURIAndSha "https://github.com/vash/dup/releases/download/{{ .TagName }}/dup_{{ .TagName }}_darwin_amd64.tar.gz" .TagName }}
    bin: kubectl-dup
  - selector:
      matchLabels:
        os: darwin
        arch: arm64
    {{addURIAndSha "https://github.com/vash/dup/releases/download/{{ .TagName }}/dup_{{ .TagName }}_darwin_arm64.tar.gz" .TagName }}
    bin: kubectl-dup
  - selector:
      matchLabels:
        os: linux
        arch: amd64
    {{addURIAndSha "https://github.com/vash/dup/releases/download/{{ .TagName }}/dup_{{ .TagName }}_linux_amd64.tar.gz" .TagName }}
    bin: kubectl-dup
  - selector:
      matchLabels:
        os: windows
        arch: amd64
    {{addURIAndSha "https://github.com/vash/dup/releases/download/{{ .TagName }}/dup_{{ .TagName }}_windows_amd64.zip" .TagName }}
    bin: kubectl-dup.exe
07070100000006000081A400000000000000000000000166C10ABB0000042E000000000000000000000000000000000000001A00000000kubectl-dup-0.3.2/LICENSEMIT License

Copyright (c) 2024 Eliran Barnoy

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall 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.
07070100000007000081A400000000000000000000000166C10ABB0000081D000000000000000000000000000000000000001C00000000kubectl-dup-0.3.2/README.md![Dup](imgs/dup.svg)

# dup - kubectl Plugin for duplication of Kubernetes Resources

This plugin is designed for on-the-fly duplication of Kubernetes resources.
It focuses on providing a convenient way to edit resources before duplication,
with a specific emphasis on Pods to create a fine-tuned resource quickly.
This tool can be used for debugging running containers without them crashing,
and simplifying the administration and general interaction with Kubernetes clusters.

[![asciicast](https://asciinema.org/a/C8Lr4dCXGOCA6Pc0GB7xXWSyG.svg)](https://asciinema.org/a/C8Lr4dCXGOCA6Pc0GB7xXWSyG)

## Installation

### Using Krew (Kubectl Plugin Manager)

```bash
kubectl krew install dup
```

### Manual Installation

Download the latest release from the GitHub releases page.
Extract the binary from the archive.
Move the binary to a directory in your system's PATH.

### Usage

```bash
kubectl dup [options] <resource-type,resource-type-2> <resource-name> <generated-resource-name-prefix>
```

## Examples

```bash
# duplicate a pod of deployment "my-deployment" without opening edit window
kubectl dup deployment my-deployment -pk

# duplicate a specific pod, regardless of what it belongs to,
# and disable liveness probes on it.
kubectl dup pod my-pod -d
```

## Features

- Resource Duplication: Duplicate Kubernetes resources with ease.
- Interactive Editing: Open resources for manual editing before applying changes.
- Pod Focused: Designed to streamline debugging and administration of Pods.

## Options

- -d, --disable-probes Automatically disable readiness and liveness probes for duplicated pods.
- -h, --help: Display help information.
- -p, --pod: Duplicate pod of complex objects, supported objects: 'StatefulSet','Deployment','CronJob','Job'.
- -k, --skip-edit: Skip editing duplicated resource before creation

## Contributing

We welcome contributions! If you have any ideas, enhancements, or bug fixes,
feel free to open an issue or submit a pull request.

## License

This project is licensed under the MIT License - see the LICENSE file for details.
07070100000008000041ED00000000000000000000000266C10ABB00000000000000000000000000000000000000000000001600000000kubectl-dup-0.3.2/cmd07070100000009000081A400000000000000000000000166C10ABB00000A1E000000000000000000000000000000000000001E00000000kubectl-dup-0.3.2/cmd/root.gopackage cmd

import (
	"errors"
	"fmt"

	"dup/pkg/editor"
	"dup/pkg/util"

	"github.com/spf13/cobra"
	"k8s.io/cli-runtime/pkg/genericclioptions"
	cmdutil "k8s.io/kubectl/pkg/cmd/util"
	"k8s.io/kubectl/pkg/util/completion"
)

var (
	kubeconfig string
	namespace  string
	deployment string
	edit       bool
	SilentErr  = errors.New("SilentErr")
)

func validateArgs(cmd *cobra.Command, args []string) error {
	if len(args) < 1 || len(args) > 2 {
		return fmt.Errorf("requires exactly 1 or 2 arguments")
	}
	for _, arg := range args {
		if !util.IsValidPod(arg) {
			return fmt.Errorf("invalid argument: %s", arg)
		}
	}
	return nil
}
func NewRootCmd(ioStreams genericclioptions.IOStreams) *cobra.Command {
	o := editor.NewEditOptions(ioStreams)
	kubeConfigFlags := defaultConfigFlags().WithWarningPrinter(o.IOStreams)
	matchVersionKubeConfigFlags := cmdutil.NewMatchVersionFlags(kubeConfigFlags)
	f := cmdutil.NewFactory(matchVersionKubeConfigFlags)

	var rootCmd = &cobra.Command{
		Use:               "kubectl dup [options] <resource-type, ...resource-type-n> <resource> [output-resource-prefix]",
		Short:             "Duplicate a pod out of a Deployment",
		ValidArgsFunction: completion.ResourceTypeAndNameCompletionFunc(f),
		Args:              cobra.RangeArgs(2, 3),
		Run: func(cmd *cobra.Command, args []string) {
			cmdutil.CheckErr(o.Complete(f, args, cmd))
			cmdutil.CheckErr(o.Run())
		},
	}

	rootCmd.Flags().BoolVarP(&o.DuplicateOptions.DuplicateInnerPod, "pod", "p", false, "Duplicate pod of resource, currently only applies for: 'StatefulSet','Deployment','CronJob','Job'")
	rootCmd.Flags().BoolVarP(&o.DuplicateOptions.DisableProbes, "disable-probes", "d", true, "Disable Readiness and liveness probes for duplicated pods only (requires '-p' for complex resources)")
	rootCmd.Flags().BoolVarP(&o.DuplicateOptions.LoopCommand, "command-loop", "l", false, "Changes running command to an infinite loop (currently : \"tail -f /dev/null\"")
	rootCmd.Flags().BoolVarP(&o.SkipEdit, "skip-edit", "k", false, "Skip editing duplicated resource before creation")
	rootCmd.Flags().BoolVar(&o.WindowsLineEndings, "windows-line-endings", o.WindowsLineEndings,
		"Defaults to the line ending native to your platform.")

	kubeConfigFlags.AddFlags(rootCmd.Flags())
	matchVersionKubeConfigFlags.AddFlags(rootCmd.Flags())
	cmdutil.AddValidateFlags(rootCmd)
	o.PrintFlags.AddFlags(rootCmd)
	return rootCmd
}

func defaultConfigFlags() *genericclioptions.ConfigFlags {
	return genericclioptions.NewConfigFlags(true).WithDeprecatedPasswordFlag().WithDiscoveryBurst(300).WithDiscoveryQPS(50.0)
}
0707010000000A000081A400000000000000000000000166C10ABB00000E71000000000000000000000000000000000000001900000000kubectl-dup-0.3.2/go.modmodule dup

go 1.22.0

toolchain go1.22.6

require (
	github.com/evanphx/json-patch v5.9.0+incompatible
	github.com/google/uuid v1.6.0
	github.com/spf13/cobra v1.8.1
	k8s.io/api v0.31.0
	k8s.io/apimachinery v0.31.0
	k8s.io/cli-runtime v0.31.0
	k8s.io/client-go v0.31.0
	k8s.io/klog/v2 v2.130.1
	k8s.io/kubectl v0.31.0
)

require (
	github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
	github.com/MakeNowJust/heredoc v1.0.0 // indirect
	github.com/blang/semver/v4 v4.0.0 // indirect
	github.com/chai2010/gettext-go v1.0.3 // indirect
	github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
	github.com/emicklei/go-restful/v3 v3.12.1 // indirect
	github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect
	github.com/fatih/camelcase v1.0.0 // indirect
	github.com/fxamacker/cbor/v2 v2.7.0 // indirect
	github.com/go-errors/errors v1.5.1 // indirect
	github.com/go-logr/logr v1.4.2 // indirect
	github.com/go-openapi/jsonpointer v0.21.0 // indirect
	github.com/go-openapi/jsonreference v0.21.0 // indirect
	github.com/go-openapi/swag v0.23.0 // indirect
	github.com/gogo/protobuf v1.3.2 // indirect
	github.com/golang/protobuf v1.5.4 // indirect
	github.com/google/btree v1.1.2 // indirect
	github.com/google/gnostic-models v0.6.8 // indirect
	github.com/google/go-cmp v0.6.0 // indirect
	github.com/google/gofuzz v1.2.0 // indirect
	github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
	github.com/gorilla/websocket v1.5.3 // indirect
	github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
	github.com/imdario/mergo v0.3.16 // indirect
	github.com/inconshreveable/mousetrap v1.1.0 // indirect
	github.com/josharian/intern v1.0.0 // indirect
	github.com/json-iterator/go v1.1.12 // indirect
	github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
	github.com/mailru/easyjson v0.7.7 // indirect
	github.com/mitchellh/go-wordwrap v1.0.1 // indirect
	github.com/moby/spdystream v0.5.0 // indirect
	github.com/moby/term v0.5.0 // indirect
	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
	github.com/modern-go/reflect2 v1.0.2 // indirect
	github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
	github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
	github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
	github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
	github.com/pkg/errors v0.9.1 // indirect
	github.com/russross/blackfriday/v2 v2.1.0 // indirect
	github.com/spf13/pflag v1.0.5 // indirect
	github.com/x448/float16 v0.8.4 // indirect
	github.com/xlab/treeprint v1.2.0 // indirect
	go.starlark.net v0.0.0-20240725214946-42030a7cedce // indirect
	golang.org/x/net v0.28.0 // indirect
	golang.org/x/oauth2 v0.22.0 // indirect
	golang.org/x/sync v0.8.0 // indirect
	golang.org/x/sys v0.24.0 // indirect
	golang.org/x/term v0.23.0 // indirect
	golang.org/x/text v0.17.0 // indirect
	golang.org/x/time v0.6.0 // indirect
	google.golang.org/protobuf v1.34.2 // indirect
	gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
	gopkg.in/inf.v0 v0.9.1 // indirect
	gopkg.in/yaml.v2 v2.4.0 // indirect
	gopkg.in/yaml.v3 v3.0.1 // indirect
	k8s.io/component-base v0.31.0 // indirect
	k8s.io/kube-openapi v0.0.0-20240812233141-91dab695df6f // indirect
	k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect
	sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
	sigs.k8s.io/kustomize/api v0.17.3 // indirect
	sigs.k8s.io/kustomize/kyaml v0.17.2 // indirect
	sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
	sigs.k8s.io/yaml v1.4.0 // indirect
)
0707010000000B000081A400000000000000000000000166C10ABB00005104000000000000000000000000000000000000001900000000kubectl-dup-0.3.2/go.sumgithub.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ=
github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
github.com/chai2010/gettext-go v1.0.3 h1:9liNh8t+u26xl5ddmWLmsOsdNLwkdRTg5AG+JnTiM80=
github.com/chai2010/gettext-go v1.0.3/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA=
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/emicklei/go-restful/v3 v3.12.1 h1:PJMDIM/ak7btuL8Ex0iYET9hxM3CI2sjZtzpL63nKAU=
github.com/emicklei/go-restful/v3 v3.12.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/evanphx/json-patch v5.9.0+incompatible h1:fBXyNpNMuTTDdquAq/uisOr2lShz4oaXpDTX2bLe7ls=
github.com/evanphx/json-patch v5.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f h1:Wl78ApPPB2Wvf/TIe2xdyJxTlb6obmF18d8QdkxNDu4=
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f/go.mod h1:OSYXu++VVOHnXeitef/D8n/6y4QV8uLHSFXX4NeXMGc=
github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8=
github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc=
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
github.com/go-errors/errors v1.5.1 h1:ZwEMSLRCapFLflTpT7NKaAc7ukJ8ZPEjzlxt8rPN8bk=
github.com/go-errors/errors v1.5.1/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ=
github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4=
github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 h1:FKHo8hFI3A+7w0aUQuYXQ+6EN5stWmeY/AZqtM8xk9k=
github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA=
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0=
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE=
github.com/lithammer/dedent v1.1.0 h1:VNzHMVCBNG1j0fh3OrsFRkVUwStdDArbgBWoPAffktY=
github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
github.com/moby/spdystream v0.5.0 h1:7r0J1Si3QO/kjRitvSLVVFUjxMEb/YLj6S9FF62JBCU=
github.com/moby/spdystream v0.5.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI=
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0=
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
github.com/onsi/ginkgo/v2 v2.20.0 h1:PE84V2mHqoT1sglvHc8ZdQtPcwmvvt29WLEEO3xmdZw=
github.com/onsi/ginkgo/v2 v2.20.0/go.mod h1:lG9ey2Z29hR41WMVthyJBGUBcBhGOtoPF2VFMvBXFCI=
github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k=
github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY=
github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ=
github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.starlark.net v0.0.0-20240725214946-42030a7cedce h1:YyGqCjZtGZJ+mRPaenEiB87afEO2MFRzLiJNZ0Z0bPw=
go.starlark.net v0.0.0-20240725214946-42030a7cedce/go.mod h1:YKMCv9b1WrfWmeqdV5MAuEHWsu5iC+fe6kYl2sQjdI8=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
golang.org/x/oauth2 v0.22.0 h1:BzDx2FehcG7jJwgWLELCdmLuxk2i+x9UDpSiss2u0ZA=
golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU=
golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4=
gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
k8s.io/api v0.31.0 h1:b9LiSjR2ym/SzTOlfMHm1tr7/21aD7fSkqgD/CVJBCo=
k8s.io/api v0.31.0/go.mod h1:0YiFF+JfFxMM6+1hQei8FY8M7s1Mth+z/q7eF1aJkTE=
k8s.io/apimachinery v0.31.0 h1:m9jOiSr3FoSSL5WO9bjm1n6B9KROYYgNZOb4tyZ1lBc=
k8s.io/apimachinery v0.31.0/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo=
k8s.io/cli-runtime v0.31.0 h1:V2Q1gj1u3/WfhD475HBQrIYsoryg/LrhhK4RwpN+DhA=
k8s.io/cli-runtime v0.31.0/go.mod h1:vg3H94wsubuvWfSmStDbekvbla5vFGC+zLWqcf+bGDw=
k8s.io/client-go v0.31.0 h1:QqEJzNjbN2Yv1H79SsS+SWnXkBgVu4Pj3CJQgbx0gI8=
k8s.io/client-go v0.31.0/go.mod h1:Y9wvC76g4fLjmU0BA+rV+h2cncoadjvjjkkIGoTLcGU=
k8s.io/component-base v0.31.0 h1:/KIzGM5EvPNQcYgwq5NwoQBaOlVFrghoVGr8lG6vNRs=
k8s.io/component-base v0.31.0/go.mod h1:TYVuzI1QmN4L5ItVdMSXKvH7/DtvIuas5/mm8YT3rTo=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20240812233141-91dab695df6f h1:bnWtxXWdAl5bVOCEPoNdvMkyj6cTW3zxHuwKIakuV9w=
k8s.io/kube-openapi v0.0.0-20240812233141-91dab695df6f/go.mod h1:G0W3eI9gG219NHRq3h5uQaRBl4pj4ZpwzRP5ti8y770=
k8s.io/kubectl v0.31.0 h1:kANwAAPVY02r4U4jARP/C+Q1sssCcN/1p9Nk+7BQKVg=
k8s.io/kubectl v0.31.0/go.mod h1:pB47hhFypGsaHAPjlwrNbvhXgmuAr01ZBvAIIUaI8d4=
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A=
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
sigs.k8s.io/kustomize/api v0.17.3 h1:6GCuHSsxq7fN5yhF2XrC+AAr8gxQwhexgHflOAD/JJU=
sigs.k8s.io/kustomize/api v0.17.3/go.mod h1:TuDH4mdx7jTfK61SQ/j1QZM/QWR+5rmEiNjvYlhzFhc=
sigs.k8s.io/kustomize/kyaml v0.17.2 h1:+AzvoJUY0kq4QAhH/ydPHHMRLijtUKiyVyh7fOSshr0=
sigs.k8s.io/kustomize/kyaml v0.17.2/go.mod h1:9V0mCjIEYjlXuCdYsSXvyoy2BTsLESH7TlGV81S282U=
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
0707010000000C000041ED00000000000000000000000266C10ABB00000000000000000000000000000000000000000000001700000000kubectl-dup-0.3.2/imgs0707010000000D000081A400000000000000000000000166C10ABB00001742000000000000000000000000000000000000001F00000000kubectl-dup-0.3.2/imgs/dup.svg<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
	 width="1665.086px" height="567.029px" viewBox="0 0 1665.086 567.029" enable-background="new 0 0 1665.086 567.029"
	 xml:space="preserve">
<g>
	<polygon fill="#FFFFFF" points="787.366,94.488 603.874,316.331 881.293,472.541 1054.531,256.159 	"/>
	<g>
		<g>
			<path fill="#FED93E" d="M897.023,242.629c9.98,0.062,17.896,3.685,23.761,10.88c5.864,7.196,8.75,17.4,8.674,30.632
				c-0.047,6.396-1.026,12.163-2.955,17.299c-1.937,5.133-4.478,9.487-7.656,13.041c-3.165,3.559-6.806,6.301-10.939,8.232
				c-4.138,1.915-8.481,2.871-13.041,2.838c-4.543-0.028-8.498-0.875-11.849-2.514c-3.357-1.654-6.75-3.888-10.203-6.731
				l0.565,13.494l3.257,136.029l-11.897-9.969l-4.314-211.512l11.06,0.066l1.076,9.276l0.494,0.008
				c3.163-3.024,6.785-5.627,10.866-7.818C887.989,243.686,892.367,242.601,897.023,242.629z M894.027,253.831
				c-3.682-0.031-7.16,0.847-10.428,2.613c-3.262,1.77-6.53,4.493-9.807,8.152l-0.254,41.305c3.332,3.052,6.547,5.219,9.633,6.488
				c3.073,1.258,6.242,1.9,9.494,1.929c3.147,0.022,6.105-0.693,8.873-2.139c2.781-1.442,5.211-3.495,7.276-6.134
				c2.089-2.646,3.735-5.812,4.951-9.482c1.211-3.69,1.834-7.788,1.864-12.351c0.063-9.541-1.785-16.983-5.552-22.309
				C906.319,256.557,900.972,253.87,894.027,253.831z"/>
			<path fill="#FED93E" d="M738.673,322.61c-9.972-0.065-17.88-3.69-23.748-10.89c-5.859-7.192-8.744-17.396-8.666-30.628
				c0.045-6.391,1.022-12.157,2.957-17.296c1.93-5.136,4.479-9.482,7.643-13.041c3.163-3.554,6.811-6.299,10.948-8.225
				c4.129-1.924,8.471-2.868,13.024-2.852c4.549,0.031,8.51,0.881,11.856,2.524c3.344,1.641,6.746,3.886,10.206,6.734l-0.57-13.505
				l0.685-107.991l13.192,0.635l-0.925,192.813l-11.057-0.073l-1.081-9.272l-0.487-0.005c-3.161,3.016-6.775,5.621-10.855,7.813
				C747.705,321.55,743.339,322.638,738.673,322.61z M741.673,311.408c3.692,0.022,7.161-0.851,10.431-2.616
				c3.257-1.768,6.532-4.484,9.801-8.149l0.266-41.305c-3.344-3.053-6.547-5.214-9.628-6.488c-3.087-1.259-6.254-1.903-9.508-1.929
				c-3.14-0.017-6.1,0.696-8.873,2.141c-2.773,1.446-5.202,3.492-7.271,6.134c-2.077,2.647-3.727,5.804-4.942,9.475
				c-1.219,3.685-1.837,7.797-1.864,12.351c-0.062,9.541,1.786,16.982,5.549,22.313C729.393,308.677,734.736,311.36,741.673,311.408
				z"/>
			<path fill="#FED93E" d="M825.355,242.176c8.447,0.051,14.581,2.688,18.391,7.926c3.822,5.223,5.694,12.927,5.628,23.119
				l-0.316,50.083l-13.491-0.084l0.309-48.291c0.041-7.479-1.091-12.882-3.392-16.2c-2.314-3.332-6.078-4.998-11.272-5.037
				c-4.126-0.025-7.759,1.009-10.916,3.105c-3.159,2.088-6.65,5.457-10.475,10.095l-0.353,56.099l-13.335-0.078l0.501-79.036
				l11.054,0.078l1.067,12.356l0.483,0.003c3.715-4.311,7.615-7.75,11.693-10.33C815.011,243.4,819.817,242.143,825.355,242.176z"/>
			<polygon fill="#FED93E" points="776.191,129.375 778.003,106.735 603.874,316.331 616.118,322.411 			"/>
			<polygon fill="#FED93E" points="876.363,454.39 877.537,470.674 603.874,316.331 623.133,312.935 			"/>
		</g>
	</g>
	<g>
		<g>
			<path fill="#5C2D88" d="M768.065,327.242c-9.982-0.062-17.896-3.688-23.763-10.884c-5.862-7.192-8.752-17.396-8.672-30.63
				c0.049-6.394,1.026-12.161,2.955-17.297c1.935-5.133,4.479-9.487,7.655-13.041c3.163-3.559,6.804-6.304,10.941-8.232
				c4.135-1.918,8.479-2.874,13.038-2.838c4.543,0.028,8.498,0.872,11.851,2.51c3.354,1.655,6.748,3.892,10.201,6.735l-0.565-13.494
				l-2.852-140.136l11.492,14.074l4.314,211.513l-11.059-0.067l-1.074-9.275l-0.495-0.008c-3.161,3.024-6.784,5.627-10.869,7.818
				C777.098,326.186,772.72,327.267,768.065,327.242z M771.06,316.037c3.682,0.034,7.16-0.844,10.428-2.613
				c3.265-1.767,6.529-4.49,9.809-8.149l0.255-41.305c-3.333-3.055-6.547-5.219-9.639-6.49c-3.07-1.256-6.24-1.901-9.49-1.93
				c-3.146-0.02-6.106,0.693-8.873,2.142c-2.782,1.442-5.212,3.492-7.277,6.131c-2.089,2.647-3.735,5.812-4.951,9.485
				c-1.208,3.688-1.834,7.791-1.865,12.351c-0.062,9.538,1.79,16.982,5.553,22.309C758.771,313.312,764.115,315.998,771.06,316.037z
				"/>
			<path fill="#5C2D88" d="M926.414,247.261c9.971,0.062,17.883,3.69,23.751,10.886c5.859,7.193,8.745,17.397,8.663,30.632
				c-0.041,6.388-1.022,12.157-2.957,17.296c-1.933,5.133-4.479,9.479-7.644,13.039c-3.164,3.553-6.81,6.301-10.944,8.224
				c-4.132,1.927-8.474,2.871-13.027,2.852c-4.548-0.03-8.51-0.878-11.855-2.521c-3.341-1.644-6.746-3.889-10.207-6.737l0.57,13.508
				l-0.686,107.989l-13.191-0.634l0.926-192.813l11.056,0.073l1.081,9.272l0.487,0.003c3.162-3.017,6.779-5.622,10.854-7.816
				C917.382,248.317,921.748,247.233,926.414,247.261z M923.414,258.463c-3.692-0.025-7.159,0.851-10.43,2.617
				c-3.257,1.764-6.533,4.483-9.802,8.146l-0.266,41.308c3.341,3.053,6.55,5.214,9.631,6.488c3.087,1.255,6.251,1.907,9.505,1.929
				c3.14,0.015,6.103-0.696,8.873-2.145c2.773-1.444,5.206-3.488,7.273-6.13c2.075-2.647,3.724-5.804,4.943-9.475
				c1.216-3.685,1.834-7.8,1.862-12.356c0.061-9.538-1.787-16.977-5.55-22.313C935.695,261.194,930.351,258.511,923.414,258.463z"/>
			<path fill="#5C2D88" d="M839.735,327.692c-8.452-0.051-14.585-2.685-18.395-7.923c-3.822-5.225-5.695-12.93-5.628-23.119
				l0.315-50.083l13.492,0.085l-0.305,48.287c-0.045,7.481,1.087,12.882,3.388,16.203c2.318,3.329,6.078,4.996,11.271,5.035
				c4.127,0.024,7.76-1.01,10.917-3.104c3.161-2.091,6.65-5.457,10.478-10.095l0.352-56.098l13.333,0.075l-0.501,79.038
				l-11.054-0.078l-1.067-12.359h-0.481c-3.718,4.309-7.617,7.746-11.695,10.327C850.076,326.468,845.27,327.726,839.735,327.692z"
				/>
			<polygon fill="#5C2D88" points="888.896,440.493 888.683,463.928 1061.212,253.54 1047.771,246.867 			"/>
			<polygon fill="#5C2D88" points="790.461,112.922 788.327,94.965 1050.626,248.284 1041.954,256.937 			"/>
		</g>
	</g>
</g>
</svg>
0707010000000E000081A400000000000000000000000166C10ABB0000008E000000000000000000000000000000000000001B00000000kubectl-dup-0.3.2/justfiledup:
  go mod download && GOOS=linux GOARCH=amd64 go build -a -ldflags="-s -w" -o ./bin/kubectl-dup .
clean:
  rm -rf bin
test:
  go test ...
0707010000000F000081A400000000000000000000000166C10ABB00000108000000000000000000000000000000000000001A00000000kubectl-dup-0.3.2/main.gopackage main

import (
	cmd "dup/cmd"
	"os"

	"k8s.io/cli-runtime/pkg/genericiooptions"
)

func main() {
	root := cmd.NewRootCmd(genericiooptions.IOStreams{In: os.Stdin, Out: os.Stdout, ErrOut: os.Stderr})
	if err := root.Execute(); err != nil {
		os.Exit(1)
	}
}
07070100000010000041ED00000000000000000000000266C10ABB00000000000000000000000000000000000000000000001600000000kubectl-dup-0.3.2/pkg07070100000011000041ED00000000000000000000000266C10ABB00000000000000000000000000000000000000000000002000000000kubectl-dup-0.3.2/pkg/duplicate07070100000012000081A400000000000000000000000166C10ABB0000111E000000000000000000000000000000000000002D00000000kubectl-dup-0.3.2/pkg/duplicate/duplicate.gopackage duplicate

import (
	duputil "dup/pkg/util"
	"fmt"
	"strings"

	appsv1 "k8s.io/api/apps/v1"
	batchv1 "k8s.io/api/batch/v1"
	corev1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/meta"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/cli-runtime/pkg/resource"
)

const LOOP_COMMAND = "tail -f /dev/null"

type PodOptions struct {
	DuplicateInnerPod bool
	DisableProbes     bool
	LoopCommand       bool
	Image             string
}

func Clone(opts *PodOptions, objects []*resource.Info) ([]*runtime.Object, error) {
	var ret []*runtime.Object
	for i := range objects {
		obj := objects[i]
		objKind := obj.Object.GetObjectKind().GroupVersionKind().Kind
		if hasPodSpec(objKind) {
			dResource, err := cloneResourceWithPod(obj.Object, opts)
			if err != nil {
				return nil, err
			}
			ret = append(ret, dResource)
		} else {
			dResource, err := cloneGenericResource(obj.Object)
			if err != nil {
				return nil, err
			}
			ret = append(ret, dResource)
		}
	}
	return ret, nil
}

func hasPodSpec(kind string) bool {
	switch kind {
	case "Deployment", "CronJob", "StatefulSet", "Job", "Pod":
		return true
	}
	return false
}

func unstructuredToType(in runtime.Object, out runtime.Object) error {
	unstructured, ok := in.(*unstructured.Unstructured)
	if !ok {
		return fmt.Errorf("Error converting runtime.Object to unstructured")
	}
	err := runtime.DefaultUnstructuredConverter.FromUnstructured(unstructured.Object, out)
	if err != nil {
		return fmt.Errorf("Error converting unstructured to Deploy: %v\n", err)
	}
	return nil
}

func cloneResourceWithPod(obj runtime.Object, opts *PodOptions) (*runtime.Object, error) {
	var dupObject runtime.Object
	var metadata *metav1.ObjectMeta
	var spec *corev1.PodSpec
	objType := obj.GetObjectKind().GroupVersionKind().Kind
	switch objType {
	case "StatefulSet":
		dupObject = &appsv1.StatefulSet{}
		unstructuredToType(obj, dupObject)
		metadata, spec = extractPod[StatefulSetAdapter](StatefulSetAdapter{dupObject.(*appsv1.StatefulSet)})
	case "Deployment":
		dupObject = &appsv1.Deployment{}
		unstructuredToType(obj, dupObject)
		metadata, spec = extractPod[DeploymentAdapter](DeploymentAdapter{dupObject.(*appsv1.Deployment)})
	case "CronJob":
		dupObject = &batchv1.CronJob{}
		unstructuredToType(obj, dupObject)
		metadata, spec = extractPod[CronJobAdapter](CronJobAdapter{dupObject.(*batchv1.CronJob)})
	case "Job":
		dupObject = &batchv1.Job{}
		unstructuredToType(obj, dupObject)
		metadata, spec = extractPod[JobAdapter](JobAdapter{dupObject.(*batchv1.Job)})
	case "Pod":
		dupObject = &corev1.Pod{}
		unstructuredToType(obj, dupObject)
		metadata, spec = extractPod[PodAdapter](PodAdapter{dupObject.(*corev1.Pod)})
	default:
		return nil, fmt.Errorf("object type %s does not have PodSpec or is not supported", objType)
	}

	applyOptions(objType, spec, metadata, opts)
	err := setSuffixedName(&dupObject)
	if err != nil {
		return nil, err
	}
	return &dupObject, nil
}

func setSuffixedName(obj *runtime.Object) error {
	accessor := meta.NewAccessor()
	name, err := accessor.Name(*obj)
	if err != nil {
		return err
	}
	suffixedName := duputil.GenerateResourceName(name)
	accessor.SetName(*obj, suffixedName)
	return nil
}

func cloneGenericResource(obj runtime.Object) (*runtime.Object, error) {
	objCopy := obj.DeepCopyObject()
	err := setSuffixedName(&objCopy)
	if err != nil {
		return nil, err
	}

	return &objCopy, nil
}
func applyOptions(kind string, spec *corev1.PodSpec, meta *metav1.ObjectMeta, opts *PodOptions) {
	if opts != nil {
		if opts.DisableProbes {
			disableProbes(spec)
		}
		if opts.LoopCommand {
			setCommand(spec)
		}
		if kind == "Pod" {
			removeOwnership(meta)
		}
	}
}

func disableProbes(podSpec *corev1.PodSpec) {
	containers := podSpec.Containers
	for i := range containers {
		containers[i].ReadinessProbe = nil
		containers[i].LivenessProbe = nil
	}
}

func setCommand(podSpec *corev1.PodSpec) {
	command := strings.Split(LOOP_COMMAND, " ")
	containers := podSpec.Containers
	for i := range containers {
		containers[i].Command = command
	}
}

func removeOwnership(metadata *metav1.ObjectMeta) {
	delete(metadata.Labels, "app.kubernetes.io/instance")
	delete(metadata.Labels, "app.kubernetes.io/name")
	metadata.OwnerReferences = nil
	metadata.UID = ""
	metadata.ResourceVersion = ""
}
07070100000013000081A400000000000000000000000166C10ABB0000069F000000000000000000000000000000000000002E00000000kubectl-dup-0.3.2/pkg/duplicate/podextract.gopackage duplicate

import (
	appsv1 "k8s.io/api/apps/v1"
	batchv1 "k8s.io/api/batch/v1"
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

type MetadataSpecExtractor[T any] interface {
	GetPodMetadata() *metav1.ObjectMeta
	GetPodSpec() *corev1.PodSpec
}

func extractPod[T MetadataSpecExtractor[T]](obj T) (*metav1.ObjectMeta, *corev1.PodSpec) {
	return obj.GetPodMetadata(), obj.GetPodSpec()
}

type StatefulSetAdapter struct {
	*appsv1.StatefulSet
}

func (s StatefulSetAdapter) GetPodMetadata() *metav1.ObjectMeta {
	return &s.StatefulSet.Spec.Template.ObjectMeta
}

func (s StatefulSetAdapter) GetPodSpec() *corev1.PodSpec {
	return &s.StatefulSet.Spec.Template.Spec
}

type DeploymentAdapter struct {
	*appsv1.Deployment
}

func (s DeploymentAdapter) GetPodMetadata() *metav1.ObjectMeta {
	return &s.Deployment.Spec.Template.ObjectMeta
}

func (s DeploymentAdapter) GetPodSpec() *corev1.PodSpec {
	return &s.Deployment.Spec.Template.Spec
}

type CronJobAdapter struct {
	*batchv1.CronJob
}

func (s CronJobAdapter) GetPodMetadata() *metav1.ObjectMeta {
	return &s.CronJob.Spec.JobTemplate.Spec.Template.ObjectMeta
}

func (s CronJobAdapter) GetPodSpec() *corev1.PodSpec {
	return &s.CronJob.Spec.JobTemplate.Spec.Template.Spec
}

type JobAdapter struct {
	*batchv1.Job
}

func (s JobAdapter) GetPodMetadata() *metav1.ObjectMeta {
	return &s.Job.Spec.Template.ObjectMeta
}

func (s JobAdapter) GetPodSpec() *corev1.PodSpec {
	return &s.Job.Spec.Template.Spec
}

type PodAdapter struct {
	*corev1.Pod
}

func (s PodAdapter) GetPodMetadata() *metav1.ObjectMeta {
	return &s.Pod.ObjectMeta
}

func (s PodAdapter) GetPodSpec() *corev1.PodSpec {
	return &s.Pod.Spec
}
07070100000014000041ED00000000000000000000000266C10ABB00000000000000000000000000000000000000000000001D00000000kubectl-dup-0.3.2/pkg/editor07070100000015000081A400000000000000000000000166C10ABB00004909000000000000000000000000000000000000002C00000000kubectl-dup-0.3.2/pkg/editor/editoptions.go/*
Copyright 2017 The Kubernetes 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 editor

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"os"
	"path/filepath"
	goruntime "runtime"
	"strings"

	"dup/pkg/duplicate"

	jsonpatch "github.com/evanphx/json-patch"
	"github.com/spf13/cobra"
	"k8s.io/klog/v2"

	corev1 "k8s.io/api/core/v1"
	apierrors "k8s.io/apimachinery/pkg/api/errors"
	"k8s.io/apimachinery/pkg/api/meta"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/types"
	"k8s.io/apimachinery/pkg/util/validation/field"
	"k8s.io/apimachinery/pkg/util/yaml"
	"k8s.io/cli-runtime/pkg/genericclioptions"
	"k8s.io/cli-runtime/pkg/genericiooptions"
	"k8s.io/cli-runtime/pkg/printers"
	"k8s.io/cli-runtime/pkg/resource"
	_ "k8s.io/client-go/plugin/pkg/client/auth"
	cmdutil "k8s.io/kubectl/pkg/cmd/util"
	"k8s.io/kubectl/pkg/cmd/util/editor/crlf"
	"k8s.io/kubectl/pkg/scheme"
	"k8s.io/kubectl/pkg/util"
)

var SupportedSubresources = []string{"status"}
var encoder = scheme.DefaultJSONEncoder()

// EditOptions contains all the options for running edit cli command.
type EditOptions struct {
	PrintFlags *genericclioptions.PrintFlags
	ToPrinter  func(string) (printers.ResourcePrinter, error)

	OutputPatch        bool
	WindowsLineEndings bool
	SkipEdit           bool
	DuplicateOptions   *duplicate.PodOptions

	cmdutil.ValidateOptions
	ValidationDirective string

	OriginalResult *resource.Result

	CmdNamespace    string
	ApplyAnnotation bool
	ChangeCause     string

	managedFields map[types.UID][]metav1.ManagedFieldsEntry

	genericiooptions.IOStreams

	f                   cmdutil.Factory
	editPrinterOptions  *editPrinterOptions
	updatedResultGetter func(data []byte) *resource.Result

	FieldManager string

	Subresource string
}

type DuplicateOptions struct {
	DuplicatePod bool
	RemoveProbes bool
	Image        string
}

// NewEditOptions returns an initialized EditOptions instance
func NewEditOptions(ioStreams genericiooptions.IOStreams) *EditOptions {
	return &EditOptions{
		PrintFlags: genericclioptions.NewPrintFlags("edited").WithTypeSetter(scheme.Scheme),

		editPrinterOptions: &editPrinterOptions{
			// create new editor-specific PrintFlags, with all
			// output flags disabled, except json / yaml
			printFlags: (&genericclioptions.PrintFlags{
				JSONYamlPrintFlags: genericclioptions.NewJSONYamlPrintFlags(),
			}).WithDefaultOutput("yaml"),
			ext:       ".yaml",
			addHeader: true,
		},

		WindowsLineEndings: goruntime.GOOS == "windows",

		IOStreams:        ioStreams,
		DuplicateOptions: &duplicate.PodOptions{},
	}
}

type editPrinterOptions struct {
	printFlags *genericclioptions.PrintFlags
	ext        string
	addHeader  bool
}

func (e *editPrinterOptions) Complete(fromPrintFlags *genericclioptions.PrintFlags) error {
	if e.printFlags == nil {
		return fmt.Errorf("missing PrintFlags in editor printer options")
	}

	// bind output format from existing printflags
	if fromPrintFlags != nil && len(*fromPrintFlags.OutputFormat) > 0 {
		e.printFlags.OutputFormat = fromPrintFlags.OutputFormat
	}

	// prevent a commented header at the top of the user's
	// default editor if presenting contents as json.
	if *e.printFlags.OutputFormat == "json" {
		e.addHeader = false
		e.ext = ".json"
		return nil
	}

	// we default to yaml if check above is false, as only json or yaml are supported
	e.addHeader = true
	e.ext = ".yaml"
	return nil
}

func (e *editPrinterOptions) PrintObj(obj runtime.Object, out io.Writer) error {
	p, err := e.printFlags.ToPrinter()
	if err != nil {
		return err
	}
	return p.PrintObj(obj, out)
}

// Complete completes all the required options
func (o *EditOptions) Complete(f cmdutil.Factory, args []string, cmd *cobra.Command) error {
	var err error

	o.f = f
	o.editPrinterOptions.Complete(o.PrintFlags)

	o.CmdNamespace, _, err = f.ToRawKubeConfigLoader().Namespace()
	if err != nil {
		return err
	}

	o.ValidationDirective, err = cmdutil.GetValidationDirective(cmd)
	if err != nil {
		return err
	}

	b := f.NewBuilder().
		Unstructured().
		ResourceTypeOrNameArgs(true, args...).
		NamespaceParam(o.CmdNamespace).DefaultNamespace().
		ContinueOnError().
		Flatten().
		Do()

	err = b.Err()
	if err != nil {
		return err
	}

	objects, err := b.Infos()
	if err != nil {
		return err
	}

	resources, err := duplicate.Clone(o.DuplicateOptions, objects)
	if err != nil {
		return err
	}

	resourceObjects, err := objsBody(resources)
	if err != nil {
		return err
	}
	result, err := o.Build(resourceObjects, o.ValidationDirective)
	if err != nil {
		return err
	}

	o.OriginalResult = result

	o.updatedResultGetter = func(data []byte) *resource.Result {
		// resource builder to read objects from edited data
		return f.NewBuilder().
			Unstructured().
			Stream(bytes.NewReader(data), "edited-file").
			ContinueOnError().
			Flatten().
			Do()
	}

	o.ToPrinter = func(operation string) (printers.ResourcePrinter, error) {
		o.PrintFlags.NamePrintFlags.Operation = operation
		return o.PrintFlags.ToPrinter()
	}

	return nil
}

func (o *EditOptions) createResources(obj []*resource.Info) error {
	visitor := resource.InfoListVisitor(obj)

	if err := o.restoreManagedFields(obj); err != nil {
		return err
	}

	// need to make sure the original namespace wasn't changed while editing
	if err := visitor.Visit(resource.RequireNamespace(o.CmdNamespace)); err != nil {
		return err
	}

	// iterate through all items to apply annotations
	if err := o.visitAnnotation(visitor); err != nil {
		return err
	}

	err := o.visitToCreate(visitor)
	if err != nil {
		return err
	}
	return nil
}

// Run performs the execution
func (o *EditOptions) Run() error {
	//	CreateDuplicatePod(context.Background(), ioStreams, clientset, deployment, namespace, podName, edit)
	edit := NewDefaultEditor(editorEnvs())
	// editFn is invoked for each edit session (once with a list for normal edit, once for each individual resource in a edit-on-create invocation)
	editFn := func(obj []*resource.Info) error {
		var (
			results = editResults{}
			edited  = []byte{}
			file    string
			err     error
		)

		containsError := false
		// loop until we succeed or cancel editing
		for {
			// get the object we're going to serialize as input to the editor
			originalObj := obj[0].Object

			// generate the file to edit
			buf := &bytes.Buffer{}
			var w io.Writer = buf
			if o.WindowsLineEndings {
				w = crlf.NewCRLFWriter(w)
			}

			if o.editPrinterOptions.addHeader {
				results.header.writeTo(w)
			}

			if !containsError {
				if err := o.extractManagedFields(originalObj); err != nil {
					return preservedFile(err, results.file, o.ErrOut)
				}
				if err := o.editPrinterOptions.PrintObj(originalObj, w); err != nil {
					return preservedFile(err, results.file, o.ErrOut)
				}
			} else {
				// In case of an error, preserve the edited file.
				// Remove the comments (header) from it since we already
				// have included the latest header in the buffer above.
				buf.Write(cmdutil.ManualStrip(edited))
			}

			// launch the editor
			editedDiff := edited
			edited, file, err = edit.LaunchTempFile(fmt.Sprintf("%s-edit-", filepath.Base(os.Args[0])), o.editPrinterOptions.ext, buf)
			if err != nil {
				return preservedFile(err, results.file, o.ErrOut)
			}

			// If we're retrying the loop because of an error, and no change was made in the file, short-circuit
			if containsError && bytes.Equal(cmdutil.StripComments(editedDiff), cmdutil.StripComments(edited)) {
				return preservedFile(fmt.Errorf("%s", "Edit cancelled, no valid changes were saved."), file, o.ErrOut)
			}
			// cleanup any file from the previous pass
			if len(results.file) > 0 {
				os.Remove(results.file)
			}
			klog.V(4).Infof("User edited:\n%s", string(edited))

			// Apply validation
			schema, err := o.f.Validator(o.ValidationDirective)
			if err != nil {
				return preservedFile(err, file, o.ErrOut)
			}

			err = schema.ValidateBytes(cmdutil.StripComments(edited))
			if err != nil {
				results = editResults{
					file: file,
				}
				containsError = true
				fmt.Fprintln(o.ErrOut, results.addError(apierrors.NewInvalid(corev1.SchemeGroupVersion.WithKind("").GroupKind(),
					"", field.ErrorList{field.Invalid(nil, "The edited file failed validation", fmt.Sprintf("%v", err))}), obj[0]))
				continue
			}

			lines, err := hasLines(bytes.NewBuffer(edited))
			if err != nil {
				return preservedFile(err, file, o.ErrOut)
			}
			if !lines {
				os.Remove(file)
				fmt.Fprintln(o.ErrOut, "Edit cancelled, saved file was empty.")
				return nil
			}

			results = editResults{
				file: file,
			}

			// parse the edited file
			updatedInfos, err := o.updatedResultGetter(edited).Infos()
			if err != nil {
				// syntax error
				containsError = true
				results.header.reasons = append(results.header.reasons, editReason{head: fmt.Sprintf("The edited file had a syntax error: %v", err)})
				continue
			}

			containsError = false

			// restore managed fields to original object
			if err := o.restoreManagedFields(obj); err != nil {
				return preservedFile(err, file, o.ErrOut)
			}

			err = o.createResources(updatedInfos)
			if err != nil {
				return preservedFile(err, results.file, o.ErrOut)
			}

			if len(results.edit) == 0 {
				if results.notfound == 0 {
					os.Remove(file)
				} else {
					fmt.Fprintf(o.Out, "The edits you made on deleted resources have been saved to %q\n", file)
				}
				return nil
			}

			if len(results.header.reasons) > 0 {
				containsError = true
			}
		}
	}
	return o.OriginalResult.Visit(func(info *resource.Info, err error) error {
		objects := []*resource.Info{info}

		if o.SkipEdit {
			err := o.createResources(objects)
			if err != nil {
				return err
			}
			return nil
		}
		return editFn(objects)
	})
}

func (o *EditOptions) Build(reader io.Reader, validate string) (*resource.Result, error) {
	schema, err := o.f.Validator(validate)
	if err != nil {
		return nil, err
	}

	result := o.f.NewBuilder().
		Unstructured().
		Schema(schema).
		Stream(reader, "").
		Do()

	err = result.Err()
	if err != nil {
		return nil, err
	}
	return result, nil
}

func objBody(obj runtime.Object) (io.ReadCloser, error) {
	encoded, err := runtime.Encode(encoder, obj)
	if err != nil {
		return nil, err
	}
	return io.NopCloser(bytes.NewReader([]byte(encoded))), nil
}

func objsBody(objs []*runtime.Object) (io.Reader, error) {
	var readers []io.Reader
	for _, obj := range objs {
		encoded, err := runtime.Encode(encoder, *obj)
		if err != nil {
			return nil, err
		}
		reader := bytes.NewReader([]byte(encoded))
		readers = append(readers, reader)
	}
	return io.MultiReader(readers...), nil
}

func (o *EditOptions) extractManagedFields(obj runtime.Object) error {
	o.managedFields = make(map[types.UID][]metav1.ManagedFieldsEntry)
	if meta.IsListType(obj) {
		err := meta.EachListItem(obj, func(obj runtime.Object) error {
			uid, mf, err := clearManagedFields(obj)
			if err != nil {
				return err
			}
			o.managedFields[uid] = mf
			return nil
		})
		return err
	}
	uid, mf, err := clearManagedFields(obj)
	if err != nil {
		return err
	}
	o.managedFields[uid] = mf
	return nil
}

func clearManagedFields(obj runtime.Object) (types.UID, []metav1.ManagedFieldsEntry, error) {
	metaObjs, err := meta.Accessor(obj)
	if err != nil {
		return "", nil, err
	}
	mf := metaObjs.GetManagedFields()
	metaObjs.SetManagedFields(nil)
	return metaObjs.GetUID(), mf, nil
}

func (o *EditOptions) restoreManagedFields(infos []*resource.Info) error {
	for _, info := range infos {
		metaObjs, err := meta.Accessor(info.Object)
		if err != nil {
			return err
		}
		mf := o.managedFields[metaObjs.GetUID()]
		metaObjs.SetManagedFields(mf)
	}
	return nil
}

func (o *EditOptions) annotationPatch(update *resource.Info) error {
	patch, _, patchType, err := GetApplyPatch(update.Object.(runtime.Unstructured))
	if err != nil {
		return err
	}
	mapping := update.ResourceMapping()
	client, err := o.f.UnstructuredClientForMapping(mapping)
	if err != nil {
		return err
	}
	helper := resource.NewHelper(client, mapping).
		WithFieldManager(o.FieldManager).
		WithFieldValidation(o.ValidationDirective).
		WithSubresource(o.Subresource)
	_, err = helper.Patch(o.CmdNamespace, update.Name, patchType, patch, nil)
	return err
}

// GetApplyPatch is used to get and apply patches
func GetApplyPatch(obj runtime.Unstructured) ([]byte, []byte, types.PatchType, error) {
	beforeJSON, err := encodeToJSON(obj)
	if err != nil {
		return nil, []byte(""), types.MergePatchType, err
	}
	objCopy := obj.DeepCopyObject()
	accessor := meta.NewAccessor()
	annotations, err := accessor.Annotations(objCopy)
	if err != nil {
		return nil, beforeJSON, types.MergePatchType, err
	}
	if annotations == nil {
		annotations = map[string]string{}
	}
	annotations[corev1.LastAppliedConfigAnnotation] = string(beforeJSON)
	accessor.SetAnnotations(objCopy, annotations)
	afterJSON, err := encodeToJSON(objCopy.(runtime.Unstructured))
	if err != nil {
		return nil, beforeJSON, types.MergePatchType, err
	}
	patch, err := jsonpatch.CreateMergePatch(beforeJSON, afterJSON)
	return patch, beforeJSON, types.MergePatchType, err
}

func encodeToJSON(obj runtime.Unstructured) ([]byte, error) {
	serialization, err := runtime.Encode(unstructured.UnstructuredJSONScheme, obj)
	if err != nil {
		return nil, err
	}
	js, err := yaml.ToJSON(serialization)
	if err != nil {
		return nil, err
	}
	return js, nil
}

func (o *EditOptions) visitToCreate(createVisitor resource.Visitor) error {
	err := createVisitor.Visit(func(info *resource.Info, incomingErr error) error {
		obj, err := resource.NewHelper(info.Client, info.Mapping).
			WithFieldManager(o.FieldManager).
			WithFieldValidation(o.ValidationDirective).
			Create(info.Namespace, true, info.Object)
		if err != nil {
			return err
		}
		info.Refresh(obj, true)
		printer, err := o.ToPrinter("created")
		if err != nil {
			return err
		}
		return printer.PrintObj(info.Object, o.Out)
	})
	return err
}

func (o *EditOptions) visitAnnotation(annotationVisitor resource.Visitor) error {
	// iterate through all items to apply annotations
	err := annotationVisitor.Visit(func(info *resource.Info, incomingErr error) error {
		// put configuration annotation in "updates"
		if o.ApplyAnnotation {
			if err := util.CreateOrUpdateAnnotation(true, info.Object, scheme.DefaultJSONEncoder()); err != nil {
				return err
			}
		}

		return nil

	})
	return err
}

// editReason preserves a message about the reason this file must be edited again
type editReason struct {
	head  string
	other []string
}

// editHeader includes a list of reasons the edit must be retried
type editHeader struct {
	reasons []editReason
}

// writeTo outputs the current header information into a stream
func (h *editHeader) writeTo(w io.Writer) error {
	fmt.Fprint(w, `# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
#
`)
	for _, r := range h.reasons {
		if len(r.other) > 0 {
			fmt.Fprintf(w, "# %s:\n", hashOnLineBreak(r.head))
		} else {
			fmt.Fprintf(w, "# %s\n", hashOnLineBreak(r.head))
		}
		for _, o := range r.other {
			fmt.Fprintf(w, "# * %s\n", hashOnLineBreak(o))
		}
		fmt.Fprintln(w, "#")
	}
	return nil
}

// editResults capture the result of an update
type editResults struct {
	header    editHeader
	retryable int
	notfound  int
	edit      []*resource.Info
	file      string
}

func (r *editResults) addError(err error, info *resource.Info) string {
	resourceString := info.Mapping.Resource.Resource
	if len(info.Mapping.Resource.Group) > 0 {
		resourceString = resourceString + "." + info.Mapping.Resource.Group
	}

	switch {
	case apierrors.IsInvalid(err):
		r.edit = append(r.edit, info)
		reason := editReason{
			head: fmt.Sprintf("%s %q was not valid", resourceString, info.Name),
		}
		if err, ok := err.(apierrors.APIStatus); ok {
			if details := err.Status().Details; details != nil {
				for _, cause := range details.Causes {
					reason.other = append(reason.other, fmt.Sprintf("%s: %s", cause.Field, cause.Message))
				}
			}
		}
		r.header.reasons = append(r.header.reasons, reason)
		return fmt.Sprintf("error: %s %q is invalid", resourceString, info.Name)
	case apierrors.IsNotFound(err):
		r.notfound++
		return fmt.Sprintf("error: %s %q could not be found on the server", resourceString, info.Name)
	default:
		r.retryable++
		return fmt.Sprintf("error: %s %q could not be patched: %v", resourceString, info.Name, err)
	}
}

// preservedFile writes out a message about the provided file if it exists to the
// provided output stream when an error happens. Used to notify the user where
// their updates were preserved.
func preservedFile(err error, path string, out io.Writer) error {
	if len(path) > 0 {
		if _, err := os.Stat(path); !os.IsNotExist(err) {
			fmt.Fprintf(out, "A copy of your changes has been stored to %q\n", path)
		}
	}
	return err
}

// hasLines returns true if any line in the provided stream is non empty - has non-whitespace
// characters, or the first non-whitespace character is a '#' indicating a comment. Returns
// any errors encountered reading the stream.
func hasLines(r io.Reader) (bool, error) {
	// TODO: if any files we read have > 64KB lines, we'll need to switch to bytes.ReadLine
	// TODO: probably going to be secrets
	s := bufio.NewScanner(r)
	for s.Scan() {
		if line := strings.TrimSpace(s.Text()); len(line) > 0 && line[0] != '#' {
			return true, nil
		}
	}
	if err := s.Err(); err != nil && err != io.EOF {
		return false, err
	}
	return false, nil
}

// hashOnLineBreak returns a string built from the provided string by inserting any necessary '#'
// characters after '\n' characters, indicating a comment.
func hashOnLineBreak(s string) string {
	r := ""
	for i, ch := range s {
		j := i + 1
		if j < len(s) && ch == '\n' && s[j] != '#' {
			r += "\n# "
		} else {
			r += string(ch)
		}
	}
	return r
}

// editorEnvs returns an ordered list of env vars to check for editor preferences.
func editorEnvs() []string {
	return []string{
		"KUBE_EDITOR",
		"EDITOR",
	}
}
07070100000016000081A400000000000000000000000166C10ABB000011CC000000000000000000000000000000000000002700000000kubectl-dup-0.3.2/pkg/editor/editor.go/*
Copyright 2015 The Kubernetes 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 editor

import (
	"fmt"
	"io"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"

	"k8s.io/klog/v2"

	"k8s.io/kubectl/pkg/util/term"
)

const (
	// sorry, blame Git
	// TODO: on Windows rely on 'start' to launch the editor associated
	// with the given file type. If we can't because of the need of
	// blocking, use a script with 'ftype' and 'assoc' to detect it.
	defaultEditor = "vi"
	defaultShell  = "/bin/bash"
	windowsEditor = "notepad"
	windowsShell  = "cmd"
)

// Editor holds the command-line args to fire up the editor
type Editor struct {
	Args  []string
	Shell bool
}

// NewDefaultEditor creates a struct Editor that uses the OS environment to
// locate the editor program, looking at EDITOR environment variable to find
// the proper command line. If the provided editor has no spaces, or no quotes,
// it is treated as a bare command to be loaded. Otherwise, the string will
// be passed to the user's shell for execution.
func NewDefaultEditor(envs []string) Editor {
	args, shell := defaultEnvEditor(envs)
	return Editor{
		Args:  args,
		Shell: shell,
	}
}

func defaultEnvShell() []string {
	shell := os.Getenv("SHELL")
	if len(shell) == 0 {
		shell = platformize(defaultShell, windowsShell)
	}
	flag := "-c"
	if shell == windowsShell {
		flag = "/C"
	}
	return []string{shell, flag}
}

func defaultEnvEditor(envs []string) ([]string, bool) {
	var editor string
	for _, env := range envs {
		if len(env) > 0 {
			editor = os.Getenv(env)
		}
		if len(editor) > 0 {
			break
		}
	}
	if len(editor) == 0 {
		editor = platformize(defaultEditor, windowsEditor)
	}
	if !strings.Contains(editor, " ") {
		return []string{editor}, false
	}
	if !strings.ContainsAny(editor, "\"'\\") {
		return strings.Split(editor, " "), false
	}
	// rather than parse the shell arguments ourselves, punt to the shell
	shell := defaultEnvShell()
	return append(shell, editor), true
}

func (e Editor) args(path string) []string {
	args := make([]string, len(e.Args))
	copy(args, e.Args)
	if e.Shell {
		last := args[len(args)-1]
		args[len(args)-1] = fmt.Sprintf("%s %q", last, path)
	} else {
		args = append(args, path)
	}
	return args
}

// Launch opens the described or returns an error. The TTY will be protected, and
// SIGQUIT, SIGTERM, and SIGINT will all be trapped.
func (e Editor) Launch(path string) error {
	if len(e.Args) == 0 {
		return fmt.Errorf("no editor defined, can't open %s", path)
	}
	abs, err := filepath.Abs(path)
	if err != nil {
		return err
	}
	args := e.args(abs)
	cmd := exec.Command(args[0], args[1:]...)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	cmd.Stdin = os.Stdin
	klog.V(5).Infof("Opening file with editor %v", args)
	if err := (term.TTY{In: os.Stdin, TryDev: true}).Safe(cmd.Run); err != nil {
		if err, ok := err.(*exec.Error); ok {
			if err.Err == exec.ErrNotFound {
				return fmt.Errorf("unable to launch the editor %q", strings.Join(e.Args, " "))
			}
		}
		return fmt.Errorf("there was a problem with the editor %q", strings.Join(e.Args, " "))
	}
	return nil
}

// LaunchTempFile reads the provided stream into a temporary file in the given directory
// and file prefix, and then invokes Launch with the path of that file. It will return
// the contents of the file after launch, any errors that occur, and the path of the
// temporary file so the caller can clean it up as needed.
func (e Editor) LaunchTempFile(prefix, suffix string, r io.Reader) ([]byte, string, error) {
	f, err := os.CreateTemp("", prefix+"*"+suffix)
	if err != nil {
		return nil, "", err
	}
	defer f.Close()
	path := f.Name()
	if _, err := io.Copy(f, r); err != nil {
		os.Remove(path)
		return nil, path, err
	}
	// This file descriptor needs to close so the next process (Launch) can claim it.
	f.Close()
	if err := e.Launch(path); err != nil {
		return nil, path, err
	}
	bytes, err := os.ReadFile(path)
	return bytes, path, err
}

func platformize(linux, windows string) string {
	if runtime.GOOS == "windows" {
		return windows
	}
	return linux
}
07070100000017000081A400000000000000000000000166C10ABB0000192E000000000000000000000000000000000000002800000000kubectl-dup-0.3.2/pkg/editor/factory.gopackage editor

import (
	"errors"
	"sync"

	corev1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/meta"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/cli-runtime/pkg/genericclioptions"
	"k8s.io/cli-runtime/pkg/resource"
	"k8s.io/client-go/discovery"
	"k8s.io/client-go/dynamic"
	"k8s.io/client-go/kubernetes"
	openapiclient "k8s.io/client-go/openapi"
	"k8s.io/client-go/openapi/cached"
	"k8s.io/client-go/rest"
	restclient "k8s.io/client-go/rest"
	"k8s.io/client-go/tools/clientcmd"
	cmdutil "k8s.io/kubectl/pkg/cmd/util"
	"k8s.io/kubectl/pkg/scheme"
	"k8s.io/kubectl/pkg/util/openapi"
	"k8s.io/kubectl/pkg/validation"
)

func NewFactory(clientGetter genericclioptions.RESTClientGetter) cmdutil.Factory {
	if clientGetter == nil {
		panic("attempt to instantiate client_access_factory with nil clientGetter")
	}
	f := &factoryImpl{
		clientGetter: clientGetter,
	}

	return f
}

func (f *factoryImpl) KubernetesClientSet() (*kubernetes.Clientset, error) {
	clientConfig, err := f.ToRESTConfig()
	if err != nil {
		return nil, err
	}
	return kubernetes.NewForConfig(clientConfig)
}

func setKubernetesDefaults(config *rest.Config) error {
	// TODO remove this hack.  This is allowing the GetOptions to be serialized.
	config.GroupVersion = &schema.GroupVersion{Group: "", Version: "v1"}

	if config.APIPath == "" {
		config.APIPath = "/api"
	}
	if config.NegotiatedSerializer == nil {
		// This codec factory ensures the resources are not converted. Therefore, resources
		// will not be round-tripped through internal versions. Defaulting does not happen
		// on the client.
		config.NegotiatedSerializer = scheme.Codecs.WithoutConversion()
	}
	return rest.SetKubernetesDefaults(config)
}

func (f *factoryImpl) ClientForMapping(mapping *meta.RESTMapping) (resource.RESTClient, error) {
	cfg, err := f.clientGetter.ToRESTConfig()
	if err != nil {
		return nil, err
	}
	if err := setKubernetesDefaults(cfg); err != nil {
		return nil, err
	}
	gvk := mapping.GroupVersionKind
	switch gvk.Group {
	case corev1.GroupName:
		cfg.APIPath = "/api"
	default:
		cfg.APIPath = "/apis"
	}
	gv := gvk.GroupVersion()
	cfg.GroupVersion = &gv
	return restclient.RESTClientFor(cfg)
}

type factoryImpl struct {
	clientGetter genericclioptions.RESTClientGetter

	// Caches OpenAPI document and parsed resources
	openAPIParser *openapi.CachedOpenAPIParser
	oapi          *openapi.CachedOpenAPIGetter
	parser        sync.Once
	getter        sync.Once
}

func (f *factoryImpl) Validator(validationDirective string) (validation.Schema, error) {
	// client-side schema validation is only performed
	// when the validationDirective is strict.
	// If the directive is warn, we rely on the ParamVerifyingSchema
	// to ignore the client-side validation and provide a warning
	// to the user that attempting warn validation when SS validation
	// is unsupported is inert.
	if validationDirective == metav1.FieldValidationIgnore {
		return validation.NullSchema{}, nil
	}

	schema := validation.ConjunctiveSchema{
		validation.NewSchemaValidation(f),
		validation.NoDoubleKeySchema{},
	}

	dynamicClient, err := f.DynamicClient()
	if err != nil {
		return nil, err
	}
	// Create the FieldValidationVerifier for use in the ParamVerifyingSchema.
	discoveryClient, err := f.ToDiscoveryClient()
	if err != nil {
		return nil, err
	}
	// Memory-cache the OpenAPI V3 responses. The disk cache behavior is determined by
	// the discovery client.
	oapiV3Client := cached.NewClient(discoveryClient.OpenAPIV3())
	queryParam := resource.QueryParamFieldValidation
	primary := resource.NewQueryParamVerifierV3(dynamicClient, oapiV3Client, queryParam)
	secondary := resource.NewQueryParamVerifier(dynamicClient, f.openAPIGetter(), queryParam)
	fallback := resource.NewFallbackQueryParamVerifier(primary, secondary)
	return validation.NewParamVerifyingSchema(schema, fallback, string(validationDirective)), nil
}

func (f *factoryImpl) openAPIGetter() discovery.OpenAPISchemaInterface {
	discovery, err := f.clientGetter.ToDiscoveryClient()
	if err != nil {
		return nil
	}
	f.getter.Do(func() {
		f.oapi = openapi.NewOpenAPIGetter(discovery)
	})

	return f.oapi
}

func (f *factoryImpl) OpenAPISchema() (openapi.Resources, error) {
	openAPIGetter := f.openAPIGetter()
	if openAPIGetter == nil {
		return nil, errors.New("no openapi getter")
	}

	// Lazily initialize the OpenAPIParser once
	f.parser.Do(func() {
		// Create the caching OpenAPIParser
		f.openAPIParser = openapi.NewOpenAPIParser(f.openAPIGetter())
	})

	// Delegate to the OpenAPIPArser
	return f.openAPIParser.Parse()
}

func (f *factoryImpl) ToRESTConfig() (*restclient.Config, error) {
	return f.clientGetter.ToRESTConfig()
}
func (f *factoryImpl) DynamicClient() (dynamic.Interface, error) {
	clientConfig, err := f.ToRESTConfig()
	if err != nil {
		return nil, err
	}
	return dynamic.NewForConfig(clientConfig)
}

func (f *factoryImpl) ToDiscoveryClient() (discovery.CachedDiscoveryInterface, error) {
	return f.clientGetter.ToDiscoveryClient()
}

func (f *factoryImpl) NewBuilder() *resource.Builder {
	// NewBuilder returns a new resource builder for structured api objects.
	return resource.NewBuilder(f.clientGetter)
}
func (f *factoryImpl) OpenAPIV3Client() (openapiclient.Client, error) {
	discovery, err := f.clientGetter.ToDiscoveryClient()
	if err != nil {
		return nil, err
	}

	return cached.NewClient(discovery.OpenAPIV3()), nil
}
func (f *factoryImpl) RESTClient() (*restclient.RESTClient, error) {
	clientConfig, err := f.ToRESTConfig()
	if err != nil {
		return nil, err
	}
	setKubernetesDefaults(clientConfig)
	return restclient.RESTClientFor(clientConfig)
}

func (f *factoryImpl) ToRESTMapper() (meta.RESTMapper, error) {
	return f.clientGetter.ToRESTMapper()
}
func (f *factoryImpl) ToRawKubeConfigLoader() clientcmd.ClientConfig {
	return f.clientGetter.ToRawKubeConfigLoader()
}
func (f *factoryImpl) UnstructuredClientForMapping(mapping *meta.RESTMapping) (resource.RESTClient, error) {
	cfg, err := f.clientGetter.ToRESTConfig()
	if err != nil {
		return nil, err
	}
	if err := restclient.SetKubernetesDefaults(cfg); err != nil {
		return nil, err
	}
	cfg.APIPath = "/apis"
	if mapping.GroupVersionKind.Group == corev1.GroupName {
		cfg.APIPath = "/api"
	}
	gv := mapping.GroupVersionKind.GroupVersion()
	cfg.ContentConfig = resource.UnstructuredPlusDefaultContentConfig()
	cfg.GroupVersion = &gv
	return restclient.RESTClientFor(cfg)
}
07070100000018000041ED00000000000000000000000266C10ABB00000000000000000000000000000000000000000000001B00000000kubectl-dup-0.3.2/pkg/util07070100000019000081A400000000000000000000000166C10ABB000005E2000000000000000000000000000000000000002300000000kubectl-dup-0.3.2/pkg/util/util.gopackage util

import (
	"fmt"
	"os"
	"regexp"

	"github.com/google/uuid"
	"k8s.io/client-go/tools/clientcmd"
	clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
)

func GetDefaultNamespace(kubeconfig string) string {
	defaultNamespace, _, err := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
		&clientcmd.ClientConfigLoadingRules{ExplicitPath: kubeconfig},
		&clientcmd.ConfigOverrides{ClusterInfo: clientcmdapi.Cluster{}}).Namespace()
	if err != nil {
		fmt.Printf("Failed getting current namespace %v\n", err)
		os.Exit(1)
	}
	return defaultNamespace
}
func GetDefaultKubeconfigPath() string {
	homeDir, err := os.UserHomeDir()
	if err != nil {
		fmt.Println("Could not get home directory:%w", err)
	}
	kubeconfigDefaultPath := homeDir + "/.kube/config"
	return kubeconfigDefaultPath
}

func GenerateResourceName(input string) string {
	var result string
	var suffix = "-dup-" + uuid.New().String()[:4]
	var maxPodNameLength = 63 - len(suffix) //RFC1035

	if len(input) > (maxPodNameLength) {
		result = input[:maxPodNameLength] + suffix
	} else {
		result = input + suffix
	}
	return result
}

func IsValidPod(podName string) bool {
	// Ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#dns-label-names
	return isValidDNSLabel(podName)
}
func isValidDNSLabel(input string) bool {
	// Regular expression for DNS label validation as per RFC 1123
	dnsLabelRegex := regexp.MustCompile(`^[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])?$`)
	return dnsLabelRegex.MatchString(input)
}
07070100000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000B00000000TRAILER!!!159 blocks
openSUSE Build Service is sponsored by