mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 19:56:01 +00:00
[kubeadm/app/cmd]switch to github.com/pkg/errors
Signed-off-by: yuexiao-wang <wang.yuexiao@zte.com.cn>
This commit is contained in:
parent
2126045bcc
commit
f9084c6ce6
@ -22,6 +22,7 @@ import (
|
||||
"io"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/renstrom/dedent"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
@ -118,10 +119,10 @@ func NewCmdCompletion(out io.Writer, boilerPlate string) *cobra.Command {
|
||||
// RunCompletion checks given arguments and executes command
|
||||
func RunCompletion(out io.Writer, boilerPlate string, cmd *cobra.Command, args []string) error {
|
||||
if len(args) == 0 {
|
||||
return fmt.Errorf("shell not specified")
|
||||
return errors.New("shell not specified")
|
||||
}
|
||||
if len(args) > 1 {
|
||||
return fmt.Errorf("too many arguments. expected only the shell type")
|
||||
return errors.New("too many arguments. expected only the shell type")
|
||||
}
|
||||
run, found := completionShells[args[0]]
|
||||
if !found {
|
||||
|
@ -24,6 +24,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/renstrom/dedent"
|
||||
"github.com/spf13/cobra"
|
||||
flag "github.com/spf13/pflag"
|
||||
@ -296,7 +297,7 @@ func getDefaultComponentConfigBytes(registration componentconfigs.Registration)
|
||||
|
||||
realobj, ok := registration.GetFromInternalConfig(&defaultedInitConfig.ClusterConfiguration)
|
||||
if !ok {
|
||||
return []byte{}, fmt.Errorf("GetFromInternalConfig failed")
|
||||
return []byte{}, errors.New("GetFromInternalConfig failed")
|
||||
}
|
||||
|
||||
return registration.Marshal(realobj)
|
||||
@ -325,7 +326,7 @@ func NewCmdConfigMigrate(out io.Writer) *cobra.Command {
|
||||
`), kubeadmapiv1alpha3.SchemeGroupVersion.String(), kubeadmapiv1beta1.SchemeGroupVersion.String(), kubeadmapiv1beta1.SchemeGroupVersion.String()),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if len(oldCfgPath) == 0 {
|
||||
kubeadmutil.CheckErr(fmt.Errorf("The --old-config flag is mandatory"))
|
||||
kubeadmutil.CheckErr(errors.New("The --old-config flag is mandatory"))
|
||||
}
|
||||
|
||||
internalcfg, err := configutil.AnyConfigFileAndDefaultsToInternal(oldCfgPath)
|
||||
@ -398,7 +399,7 @@ func NewCmdConfigUploadFromFile(out io.Writer, kubeConfigFile *string) *cobra.Co
|
||||
`), metav1.NamespaceSystem, constants.KubeadmConfigConfigMap),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if len(cfgPath) == 0 {
|
||||
kubeadmutil.CheckErr(fmt.Errorf("The --config flag is mandatory"))
|
||||
kubeadmutil.CheckErr(errors.New("The --config flag is mandatory"))
|
||||
}
|
||||
|
||||
glog.V(1).Infoln("[config] retrieving ClientSet from file")
|
||||
@ -583,7 +584,7 @@ func NewCmdConfigImagesList(out io.Writer, mockK8sVersion *string) *cobra.Comman
|
||||
func NewImagesList(cfgPath string, cfg *kubeadmapiv1beta1.InitConfiguration) (*ImagesList, error) {
|
||||
initcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfgPath, cfg)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not convert cfg to an internal cfg: %v", err)
|
||||
return nil, errors.Wrap(err, "could not convert cfg to an internal cfg")
|
||||
}
|
||||
|
||||
return &ImagesList{
|
||||
|
@ -27,6 +27,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/renstrom/dedent"
|
||||
"github.com/spf13/cobra"
|
||||
flag "github.com/spf13/pflag"
|
||||
@ -307,7 +308,7 @@ func newInitData(cmd *cobra.Command, options *initOptions) (initData, error) {
|
||||
dryRunDir := ""
|
||||
if options.dryRun {
|
||||
if dryRunDir, err = ioutil.TempDir("", "kubeadm-init-dryrun"); err != nil {
|
||||
return initData{}, fmt.Errorf("couldn't create a temporary directory: %v", err)
|
||||
return initData{}, errors.Wrap(err, "couldn't create a temporary directory")
|
||||
}
|
||||
}
|
||||
|
||||
@ -416,7 +417,7 @@ func runInit(i *initData, out io.Writer) error {
|
||||
realCertsDir := i.cfg.CertificatesDir
|
||||
certsDirToWriteTo, kubeConfigDir, manifestDir, _, err := getDirectoriesToUse(i.dryRun, i.dryRunDir, i.cfg.CertificatesDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error getting directories to use: %v", err)
|
||||
return errors.Wrap(err, "error getting directories to use")
|
||||
}
|
||||
|
||||
// certsDirToWriteTo is gonna equal cfg.CertificatesDir in the normal case, but gonna be a temp directory if dryrunning
|
||||
@ -465,13 +466,13 @@ func runInit(i *initData, out io.Writer) error {
|
||||
glog.V(1).Infof("[init] bootstraping the control plane")
|
||||
glog.V(1).Infof("[init] creating static pod manifest")
|
||||
if err := controlplanephase.CreateInitStaticPodManifestFiles(manifestDir, i.cfg); err != nil {
|
||||
return fmt.Errorf("error creating init static pod manifest files: %v", err)
|
||||
return errors.Wrap(err, "error creating init static pod manifest files")
|
||||
}
|
||||
// Add etcd static pod spec only if external etcd is not configured
|
||||
if i.cfg.Etcd.External == nil {
|
||||
glog.V(1).Infof("[init] no external etcd found. Creating manifest for local etcd static pod")
|
||||
if err := etcdphase.CreateLocalEtcdStaticPodManifestFile(manifestDir, i.cfg); err != nil {
|
||||
return fmt.Errorf("error creating local etcd static pod manifest file: %v", err)
|
||||
return errors.Wrap(err, "error creating local etcd static pod manifest file")
|
||||
}
|
||||
}
|
||||
|
||||
@ -480,14 +481,14 @@ func runInit(i *initData, out io.Writer) error {
|
||||
|
||||
// If we're dry-running, print the generated manifests
|
||||
if err := printFilesIfDryRunning(i.dryRun, manifestDir); err != nil {
|
||||
return fmt.Errorf("error printing files on dryrun: %v", err)
|
||||
return errors.Wrap(err, "error printing files on dryrun")
|
||||
}
|
||||
|
||||
// Create a kubernetes client and wait for the API server to be healthy (if not dryrunning)
|
||||
glog.V(1).Infof("creating Kubernetes client")
|
||||
client, err := createClient(i.cfg, i.dryRun)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating client: %v", err)
|
||||
return errors.Wrap(err, "error creating client")
|
||||
}
|
||||
|
||||
// waiter holds the apiclient.Waiter implementation of choice, responsible for querying the API server in various ways and waiting for conditions to be fulfilled
|
||||
@ -503,7 +504,7 @@ func runInit(i *initData, out io.Writer) error {
|
||||
|
||||
kubeletFailTempl.Execute(out, ctx)
|
||||
|
||||
return fmt.Errorf("couldn't initialize a Kubernetes cluster")
|
||||
return errors.New("couldn't initialize a Kubernetes cluster")
|
||||
}
|
||||
|
||||
// Upload currently used configuration to the cluster
|
||||
@ -511,23 +512,23 @@ func runInit(i *initData, out io.Writer) error {
|
||||
// depend on centralized information from this source in the future
|
||||
glog.V(1).Infof("[init] uploading currently used configuration to the cluster")
|
||||
if err := uploadconfigphase.UploadConfiguration(i.cfg, client); err != nil {
|
||||
return fmt.Errorf("error uploading configuration: %v", err)
|
||||
return errors.Wrap(err, "error uploading configuration")
|
||||
}
|
||||
|
||||
glog.V(1).Infof("[init] creating kubelet configuration configmap")
|
||||
if err := kubeletphase.CreateConfigMap(i.cfg, client); err != nil {
|
||||
return fmt.Errorf("error creating kubelet configuration ConfigMap: %v", err)
|
||||
return errors.Wrap(err, "error creating kubelet configuration ConfigMap")
|
||||
}
|
||||
|
||||
// PHASE 4: Mark the master with the right label/taint
|
||||
glog.V(1).Infof("[init] marking the master with right label")
|
||||
if err := markmasterphase.MarkMaster(client, i.cfg.NodeRegistration.Name, i.cfg.NodeRegistration.Taints); err != nil {
|
||||
return fmt.Errorf("error marking master: %v", err)
|
||||
return errors.Wrap(err, "error marking master")
|
||||
}
|
||||
|
||||
glog.V(1).Infof("[init] preserving the crisocket information for the master")
|
||||
if err := patchnodephase.AnnotateCRISocket(client, i.cfg.NodeRegistration.Name, i.cfg.NodeRegistration.CRISocket); err != nil {
|
||||
return fmt.Errorf("error uploading crisocket: %v", err)
|
||||
return errors.Wrap(err, "error uploading crisocket")
|
||||
}
|
||||
|
||||
// This feature is disabled by default
|
||||
@ -539,7 +540,7 @@ func runInit(i *initData, out io.Writer) error {
|
||||
|
||||
// Enable dynamic kubelet configuration for the node.
|
||||
if err := kubeletphase.EnableDynamicConfigForNode(client, i.cfg.NodeRegistration.Name, kubeletVersion); err != nil {
|
||||
return fmt.Errorf("error enabling dynamic kubelet configuration: %v", err)
|
||||
return errors.Wrap(err, "error enabling dynamic kubelet configuration")
|
||||
}
|
||||
}
|
||||
|
||||
@ -559,17 +560,17 @@ func runInit(i *initData, out io.Writer) error {
|
||||
// Create the default node bootstrap token
|
||||
glog.V(1).Infof("[init] creating RBAC rules to generate default bootstrap token")
|
||||
if err := nodebootstraptokenphase.UpdateOrCreateTokens(client, false, i.cfg.BootstrapTokens); err != nil {
|
||||
return fmt.Errorf("error updating or creating token: %v", err)
|
||||
return errors.Wrap(err, "error updating or creating token")
|
||||
}
|
||||
// Create RBAC rules that makes the bootstrap tokens able to post CSRs
|
||||
glog.V(1).Infof("[init] creating RBAC rules to allow bootstrap tokens to post CSR")
|
||||
if err := nodebootstraptokenphase.AllowBootstrapTokensToPostCSRs(client); err != nil {
|
||||
return fmt.Errorf("error allowing bootstrap tokens to post CSRs: %v", err)
|
||||
return errors.Wrap(err, "error allowing bootstrap tokens to post CSRs")
|
||||
}
|
||||
// Create RBAC rules that makes the bootstrap tokens able to get their CSRs approved automatically
|
||||
glog.V(1).Infof("[init] creating RBAC rules to automatic approval of CSRs automatically")
|
||||
if err := nodebootstraptokenphase.AutoApproveNodeBootstrapTokens(client); err != nil {
|
||||
return fmt.Errorf("error auto-approving node bootstrap tokens: %v", err)
|
||||
return errors.Wrap(err, "error auto-approving node bootstrap tokens: %v")
|
||||
}
|
||||
|
||||
// Create/update RBAC rules that makes the nodes to rotate certificates and get their CSRs approved automatically
|
||||
@ -581,21 +582,21 @@ func runInit(i *initData, out io.Writer) error {
|
||||
// Create the cluster-info ConfigMap with the associated RBAC rules
|
||||
glog.V(1).Infof("[init] creating bootstrap configmap")
|
||||
if err := clusterinfophase.CreateBootstrapConfigMapIfNotExists(client, adminKubeConfigPath); err != nil {
|
||||
return fmt.Errorf("error creating bootstrap configmap: %v", err)
|
||||
return errors.Wrap(err, "error creating bootstrap configmap")
|
||||
}
|
||||
glog.V(1).Infof("[init] creating ClusterInfo RBAC rules")
|
||||
if err := clusterinfophase.CreateClusterInfoRBACRules(client); err != nil {
|
||||
return fmt.Errorf("error creating clusterinfo RBAC rules: %v", err)
|
||||
return errors.Wrap(err, "error creating clusterinfo RBAC rules")
|
||||
}
|
||||
|
||||
glog.V(1).Infof("[init] ensuring DNS addon")
|
||||
if err := dnsaddonphase.EnsureDNSAddon(i.cfg, client); err != nil {
|
||||
return fmt.Errorf("error ensuring dns addon: %v", err)
|
||||
return errors.Wrap(err, "error ensuring dns addon")
|
||||
}
|
||||
|
||||
glog.V(1).Infof("[init] ensuring proxy addon")
|
||||
if err := proxyaddonphase.EnsureProxyAddon(i.cfg, client); err != nil {
|
||||
return fmt.Errorf("error ensuring proxy addon: %v", err)
|
||||
return errors.Wrap(err, "error ensuring proxy addon")
|
||||
}
|
||||
|
||||
// PHASE 7: Make the control plane self-hosted if feature gate is enabled
|
||||
@ -605,7 +606,7 @@ func runInit(i *initData, out io.Writer) error {
|
||||
// plane components and remove the static manifests:
|
||||
fmt.Println("[self-hosted] creating self-hosted control plane")
|
||||
if err := selfhostingphase.CreateSelfHostedControlPlane(manifestDir, kubeConfigDir, i.cfg, client, waiter, i.dryRun); err != nil {
|
||||
return fmt.Errorf("error creating self hosted control plane: %v", err)
|
||||
return errors.Wrap(err, "error creating self hosted control plane")
|
||||
}
|
||||
}
|
||||
|
||||
@ -618,7 +619,7 @@ func runInit(i *initData, out io.Writer) error {
|
||||
// Prints the join command, multiple times in case the user has multiple tokens
|
||||
for _, token := range tokens {
|
||||
if err := printJoinCommand(out, adminKubeConfigPath, token, i.skipTokenPrint); err != nil {
|
||||
return fmt.Errorf("failed to print join command: %v", err)
|
||||
return errors.Wrap(err, "failed to print join command")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
@ -418,22 +418,22 @@ func (j *Join) FetchInitConfiguration(tlsBootstrapCfg *clientcmdapi.Config) (*ku
|
||||
func (j *Join) CheckIfReadyForAdditionalControlPlane(initConfiguration *kubeadmapi.InitConfiguration) error {
|
||||
// blocks if the cluster was created without a stable control plane endpoint
|
||||
if initConfiguration.ControlPlaneEndpoint == "" {
|
||||
return fmt.Errorf("unable to add a new control plane instance a cluster that doesn't have a stable controlPlaneEndpoint address")
|
||||
return errors.New("unable to add a new control plane instance a cluster that doesn't have a stable controlPlaneEndpoint address")
|
||||
}
|
||||
|
||||
// blocks if the cluster was created without an external etcd cluster
|
||||
if initConfiguration.Etcd.External == nil {
|
||||
return fmt.Errorf("unable to add a new control plane instance on a cluster that doesn't use an external etcd")
|
||||
return errors.New("unable to add a new control plane instance on a cluster that doesn't use an external etcd")
|
||||
}
|
||||
|
||||
// blocks if control plane is self-hosted
|
||||
if features.Enabled(initConfiguration.FeatureGates, features.SelfHosting) {
|
||||
return fmt.Errorf("self-hosted clusters are deprecated and won't be supported by `kubeadm join --experimental-control-plane`")
|
||||
return errors.New("self-hosted clusters are deprecated and won't be supported by `kubeadm join --experimental-control-plane`")
|
||||
}
|
||||
|
||||
// blocks if the certificates for the control plane are stored in secrets (instead of the local pki folder)
|
||||
if features.Enabled(initConfiguration.FeatureGates, features.StoreCertsInSecrets) {
|
||||
return fmt.Errorf("certificates stored in secrets, as well as self-hosted clusters are deprecated and won't be supported by `kubeadm join --experimental-control-plane`")
|
||||
return errors.New("certificates stored in secrets, as well as self-hosted clusters are deprecated and won't be supported by `kubeadm join --experimental-control-plane`")
|
||||
}
|
||||
|
||||
// checks if the certificates that must be equal across contolplane instances are provided
|
||||
@ -561,7 +561,7 @@ func (j *Join) PostInstallControlPlane(initConfiguration *kubeadmapi.InitConfigu
|
||||
|
||||
glog.V(1).Info("[join] uploading currently used configuration to the cluster")
|
||||
if err := uploadconfigphase.UploadConfiguration(initConfiguration, client); err != nil {
|
||||
return fmt.Errorf("error uploading configuration: %v", err)
|
||||
return errors.Wrap(err, "error uploading configuration: %v")
|
||||
}
|
||||
|
||||
glog.V(1).Info("[join] marking the master with right label")
|
||||
|
@ -20,6 +20,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
@ -324,7 +325,7 @@ func createBootstrapToken(kubeConfigFile string, client clientset.Interface, cfg
|
||||
if len(internalcfg.BootstrapTokens) > 0 {
|
||||
joinCommand, err := cmdutil.GetJoinCommand(kubeConfigFile, internalcfg.BootstrapTokens[0].Token.String(), skipTokenPrint)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get join command: %v", err)
|
||||
return errors.Wrap(err, "failed to get join command")
|
||||
}
|
||||
fmt.Println(joinCommand)
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ import (
|
||||
"io"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
@ -144,7 +145,7 @@ func getKubeConfigSubCommands(out io.Writer, outDir, defaultKubernetesVersion st
|
||||
examples: userKubeconfigExample,
|
||||
cmdFunc: func(outDir string, cfg *kubeadmapi.InitConfiguration) error {
|
||||
if clientName == "" {
|
||||
return fmt.Errorf("missing required argument --client-name")
|
||||
return errors.New("missing required argument --client-name")
|
||||
}
|
||||
|
||||
// if the kubeconfig file for an additional user has to use a token, use it
|
||||
|
@ -17,8 +17,6 @@ limitations under the License.
|
||||
package phases
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
@ -190,7 +188,7 @@ func NewCmdKubeletConfigUpload() *cobra.Command {
|
||||
Example: kubeletConfigUploadExample,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if len(cfgPath) == 0 {
|
||||
kubeadmutil.CheckErr(fmt.Errorf("The --config argument is required"))
|
||||
kubeadmutil.CheckErr(errors.New("The --config argument is required"))
|
||||
}
|
||||
|
||||
// KubernetesVersion is not used, but we set it explicitly to avoid the lookup
|
||||
@ -228,7 +226,7 @@ func NewCmdKubeletAnnotateCRI() *cobra.Command {
|
||||
Example: kubeletConfigAnnotateCRIExample,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if len(cfgPath) == 0 {
|
||||
kubeadmutil.CheckErr(fmt.Errorf("The --config argument is required"))
|
||||
kubeadmutil.CheckErr(errors.New("The --config argument is required"))
|
||||
}
|
||||
|
||||
// KubernetesVersion is not used, but we set it explicitly to avoid the lookup
|
||||
@ -301,10 +299,10 @@ func NewCmdKubeletConfigEnableDynamic() *cobra.Command {
|
||||
Example: kubeletConfigEnableDynamicExample,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if len(nodeName) == 0 {
|
||||
kubeadmutil.CheckErr(fmt.Errorf("The --node-name argument is required"))
|
||||
kubeadmutil.CheckErr(errors.New("The --node-name argument is required"))
|
||||
}
|
||||
if len(kubeletVersionStr) == 0 {
|
||||
kubeadmutil.CheckErr(fmt.Errorf("The --kubelet-version argument is required"))
|
||||
kubeadmutil.CheckErr(errors.New("The --kubelet-version argument is required"))
|
||||
}
|
||||
|
||||
kubeletVersion, err := version.ParseSemantic(kubeletVersionStr)
|
||||
|
@ -19,6 +19,7 @@ package phases
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
@ -61,7 +62,7 @@ func NewCmdUploadConfig() *cobra.Command {
|
||||
Aliases: []string{"uploadconfig"},
|
||||
Run: func(_ *cobra.Command, args []string) {
|
||||
if len(cfgPath) == 0 {
|
||||
kubeadmutil.CheckErr(fmt.Errorf("the --config flag is mandatory"))
|
||||
kubeadmutil.CheckErr(errors.New("the --config flag is mandatory"))
|
||||
}
|
||||
|
||||
kubeConfigFile = cmdutil.FindExistingKubeConfig(kubeConfigFile)
|
||||
|
@ -25,6 +25,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/renstrom/dedent"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
@ -230,7 +231,7 @@ func RunCreateToken(out io.Writer, client clientset.Interface, cfgPath string, c
|
||||
if printJoinCommand {
|
||||
joinCommand, err := cmdutil.GetJoinCommand(kubeConfigFile, internalcfg.BootstrapTokens[0].Token.String(), false)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get join command: %v", err)
|
||||
return errors.Wrap(err, "failed to get join command")
|
||||
}
|
||||
fmt.Fprintln(out, joinCommand)
|
||||
} else {
|
||||
@ -271,7 +272,7 @@ func RunListTokens(out io.Writer, errW io.Writer, client clientset.Interface) er
|
||||
glog.V(1).Infoln("[token] retrieving list of bootstrap tokens")
|
||||
secrets, err := client.CoreV1().Secrets(metav1.NamespaceSystem).List(listOptions)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to list bootstrap tokens [%v]", err)
|
||||
return errors.Wrap(err, "failed to list bootstrap tokens")
|
||||
}
|
||||
|
||||
w := tabwriter.NewWriter(out, 10, 4, 3, ' ', 0)
|
||||
@ -310,7 +311,7 @@ func RunDeleteToken(out io.Writer, client clientset.Interface, tokenIDOrToken st
|
||||
tokenSecretName := bootstraputil.BootstrapTokenSecretName(tokenID)
|
||||
glog.V(1).Infoln("[token] deleting token")
|
||||
if err := client.CoreV1().Secrets(metav1.NamespaceSystem).Delete(tokenSecretName, nil); err != nil {
|
||||
return fmt.Errorf("failed to delete bootstrap token [%v]", err)
|
||||
return errors.Wrap(err, "failed to delete bootstrap token")
|
||||
}
|
||||
fmt.Fprintf(out, "bootstrap token with id %q deleted\n", tokenID)
|
||||
return nil
|
||||
|
Loading…
Reference in New Issue
Block a user