mirror of https://github.com/k3s-io/k3s
Merge pull request #60022 from fabriziopandini/kubeadm567
Automatic merge from submit-queue (batch tested with PRs 60148, 60022, 59125, 60068, 60154). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>. Refactor kubeadm join command generation **What this PR does / why we need it**: Creation of the `kubeadm join` command is implemented in three different points of kubeadm: - `kubeadm init` - `kubeadm token create` - `kubeadm phase bootstrap-token create` This PR refactor above points in order to share a common function for creating the `kubeadm join` command. **Which issue(s) this PR fixes**: Fixes [#567](https://github.com/kubernetes/kubeadm/issues/567) **Special notes for your reviewer**: While implementing the PR, I changed the order of parameters in `kubeadm join` from: ``` kubeadm join --token 8df4zm.5jyv2nrxb18y84jq 172.31.0.101:6443 --discovery-token-ca-cert-hash sha256:b62e1f70c1c6afebe36bc971b15b90f7e453f1c0fe2ddc4d92e07512f1143194 ``` to ``` kubeadm join 172.31.0.101:6443 --token 8df4zm.5jyv2nrxb18y84jq --discovery-token-ca-cert-hash sha256:b62e1f70c1c6afebe36bc971b15b90f7e453f1c0fe2ddc4d92e07512f1143194 ``` **Release note**: ```release-note NONE ```pull/6/head
commit
5e64f075dc
|
@ -36,7 +36,6 @@ go_library(
|
|||
"//cmd/kubeadm/app/phases/bootstraptoken/clusterinfo:go_default_library",
|
||||
"//cmd/kubeadm/app/phases/bootstraptoken/node:go_default_library",
|
||||
"//cmd/kubeadm/app/phases/certs:go_default_library",
|
||||
"//cmd/kubeadm/app/phases/certs/pkiutil:go_default_library",
|
||||
"//cmd/kubeadm/app/phases/controlplane:go_default_library",
|
||||
"//cmd/kubeadm/app/phases/etcd:go_default_library",
|
||||
"//cmd/kubeadm/app/phases/kubeconfig:go_default_library",
|
||||
|
@ -51,7 +50,6 @@ go_library(
|
|||
"//cmd/kubeadm/app/util/config:go_default_library",
|
||||
"//cmd/kubeadm/app/util/dryrun:go_default_library",
|
||||
"//cmd/kubeadm/app/util/kubeconfig:go_default_library",
|
||||
"//cmd/kubeadm/app/util/pubkeypin:go_default_library",
|
||||
"//cmd/kubeadm/app/util/token:go_default_library",
|
||||
"//pkg/api/legacyscheme:go_default_library",
|
||||
"//pkg/apis/core:go_default_library",
|
||||
|
@ -75,7 +73,6 @@ go_library(
|
|||
"//vendor/k8s.io/client-go/kubernetes:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/bootstrap/token/api:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/bootstrap/token/util:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/clientcmd:go_default_library",
|
||||
"//vendor/k8s.io/client-go/util/cert:go_default_library",
|
||||
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||
],
|
||||
|
|
|
@ -38,6 +38,7 @@ import (
|
|||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
|
||||
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/features"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/images"
|
||||
|
@ -46,7 +47,6 @@ import (
|
|||
clusterinfophase "k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/clusterinfo"
|
||||
nodebootstraptokenphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/node"
|
||||
certsphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/certs"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/pkiutil"
|
||||
controlplanephase "k8s.io/kubernetes/cmd/kubeadm/app/phases/controlplane"
|
||||
etcdphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/etcd"
|
||||
kubeconfigphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubeconfig"
|
||||
|
@ -61,7 +61,6 @@ import (
|
|||
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
|
||||
dryrunutil "k8s.io/kubernetes/cmd/kubeadm/app/util/dryrun"
|
||||
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/pubkeypin"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
utilsexec "k8s.io/utils/exec"
|
||||
)
|
||||
|
@ -83,7 +82,7 @@ var (
|
|||
You can now join any number of machines by running the following on each node
|
||||
as root:
|
||||
|
||||
kubeadm join --token {{.Token}} {{.MasterHostPort}} --discovery-token-ca-cert-hash {{.CAPubKeyPin}}
|
||||
{{.joinCommand}}
|
||||
|
||||
`)))
|
||||
|
||||
|
@ -467,26 +466,15 @@ func (i *Init) Run(out io.Writer) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Load the CA certificate from so we can pin its public key
|
||||
caCert, err := pkiutil.TryLoadCertFromDisk(i.cfg.CertificatesDir, kubeadmconstants.CACertAndKeyBaseName)
|
||||
// Gets the join command
|
||||
joinCommand, err := cmdutil.GetJoinCommand(kubeadmconstants.GetAdminKubeConfigPath(), i.cfg.Token, i.skipTokenPrint)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error loading ca cert from disk: %v", err)
|
||||
}
|
||||
|
||||
// Generate the Master host/port pair used by initDoneTempl
|
||||
masterHostPort, err := kubeadmutil.GetMasterHostPort(i.cfg)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error getting master host port: %v", err)
|
||||
return fmt.Errorf("failed to get join command: %v", err)
|
||||
}
|
||||
|
||||
ctx := map[string]string{
|
||||
"KubeConfigPath": adminKubeConfigPath,
|
||||
"Token": i.cfg.Token,
|
||||
"CAPubKeyPin": pubkeypin.Hash(caCert),
|
||||
"MasterHostPort": masterHostPort,
|
||||
}
|
||||
if i.skipTokenPrint {
|
||||
ctx["Token"] = "<value withheld>"
|
||||
"joinCommand": joinCommand,
|
||||
}
|
||||
|
||||
return initDoneTempl.Execute(out, ctx)
|
||||
|
|
|
@ -35,7 +35,6 @@ go_library(
|
|||
"//cmd/kubeadm/app/phases/bootstraptoken/clusterinfo:go_default_library",
|
||||
"//cmd/kubeadm/app/phases/bootstraptoken/node:go_default_library",
|
||||
"//cmd/kubeadm/app/phases/certs:go_default_library",
|
||||
"//cmd/kubeadm/app/phases/certs/pkiutil:go_default_library",
|
||||
"//cmd/kubeadm/app/phases/controlplane:go_default_library",
|
||||
"//cmd/kubeadm/app/phases/etcd:go_default_library",
|
||||
"//cmd/kubeadm/app/phases/kubeconfig:go_default_library",
|
||||
|
@ -47,7 +46,6 @@ go_library(
|
|||
"//cmd/kubeadm/app/util/apiclient:go_default_library",
|
||||
"//cmd/kubeadm/app/util/config:go_default_library",
|
||||
"//cmd/kubeadm/app/util/kubeconfig:go_default_library",
|
||||
"//cmd/kubeadm/app/util/pubkeypin:go_default_library",
|
||||
"//pkg/api/legacyscheme:go_default_library",
|
||||
"//pkg/util/normalizer:go_default_library",
|
||||
"//vendor/github.com/spf13/cobra:go_default_library",
|
||||
|
|
|
@ -34,11 +34,9 @@ import (
|
|||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/clusterinfo"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/node"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/pkiutil"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
|
||||
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/pubkeypin"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
"k8s.io/kubernetes/pkg/util/normalizer"
|
||||
)
|
||||
|
@ -137,7 +135,7 @@ func NewSubCmdBootstrapTokenAll(kubeConfigFile *string) *cobra.Command {
|
|||
kubeadmutil.CheckErr(err)
|
||||
|
||||
// Creates the bootstap token
|
||||
err = createBootstrapToken(client, cfgPath, cfg, description, usages, extraGroups, skipTokenPrint)
|
||||
err = createBootstrapToken(*kubeConfigFile, client, cfgPath, cfg, description, usages, extraGroups, skipTokenPrint)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
// Create the cluster-info ConfigMap or update if it already exists
|
||||
|
@ -194,7 +192,7 @@ func NewSubCmdBootstrapToken(kubeConfigFile *string) *cobra.Command {
|
|||
client, err := kubeconfigutil.ClientSetFromFile(*kubeConfigFile)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
err = createBootstrapToken(client, cfgPath, cfg, description, usages, extraGroups, skipTokenPrint)
|
||||
err = createBootstrapToken(*kubeConfigFile, client, cfgPath, cfg, description, usages, extraGroups, skipTokenPrint)
|
||||
kubeadmutil.CheckErr(err)
|
||||
},
|
||||
}
|
||||
|
@ -288,10 +286,6 @@ func addBootstrapTokenFlags(flagSet *pflag.FlagSet, cfg *kubeadmapiext.MasterCon
|
|||
cfgPath, "config", *cfgPath,
|
||||
"Path to kubeadm config file (WARNING: Usage of a configuration file is experimental)",
|
||||
)
|
||||
flagSet.StringVar(
|
||||
&cfg.CertificatesDir, "cert-dir", cfg.CertificatesDir,
|
||||
"The path where certificates are stored",
|
||||
)
|
||||
flagSet.StringVar(
|
||||
&cfg.Token, "token", cfg.Token,
|
||||
"The token to use for establishing bidirectional trust between nodes and masters",
|
||||
|
@ -318,7 +312,7 @@ func addBootstrapTokenFlags(flagSet *pflag.FlagSet, cfg *kubeadmapiext.MasterCon
|
|||
)
|
||||
}
|
||||
|
||||
func createBootstrapToken(client clientset.Interface, cfgPath string, cfg *kubeadmapiext.MasterConfiguration, description string, usages, extraGroups []string, skipTokenPrint bool) error {
|
||||
func createBootstrapToken(kubeConfigFile string, client clientset.Interface, cfgPath string, cfg *kubeadmapiext.MasterConfiguration, description string, usages, extraGroups []string, skipTokenPrint bool) error {
|
||||
// adding groups only makes sense for authentication
|
||||
usagesSet := sets.NewString(usages...)
|
||||
usageAuthentication := strings.TrimPrefix(bootstrapapi.BootstrapTokenUsageAuthentication, bootstrapapi.BootstrapTokenUsagePrefix)
|
||||
|
@ -337,23 +331,19 @@ func createBootstrapToken(client clientset.Interface, cfgPath string, cfg *kubea
|
|||
internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfgPath, cfg)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
// Load the CA certificate from so we can pin its public key
|
||||
caCert, err := pkiutil.TryLoadCertFromDisk(internalcfg.CertificatesDir, kubeadmconstants.CACertAndKeyBaseName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error loading ca cert from disk: %v", err)
|
||||
}
|
||||
|
||||
// Creates or updates the token
|
||||
if err := node.UpdateOrCreateToken(client, internalcfg.Token, false, internalcfg.TokenTTL.Duration, usages, extraGroups, description); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println("[bootstraptoken] Bootstrap token Created")
|
||||
if skipTokenPrint {
|
||||
internalcfg.Token = "{token}"
|
||||
}
|
||||
fmt.Println("[bootstraptoken] You can now join any number of machines by running:")
|
||||
fmt.Printf("[bootstraptoken] kubeadm join {master} --token %s --discovery-token-ca-cert-hash %s \n", internalcfg.Token, pubkeypin.Hash(caCert))
|
||||
|
||||
joinCommand, err := cmdutil.GetJoinCommand(kubeConfigFile, internalcfg.Token, skipTokenPrint)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get join command: %v", err)
|
||||
}
|
||||
fmt.Println(joinCommand)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -17,15 +17,12 @@ limitations under the License.
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/renstrom/dedent"
|
||||
|
@ -38,8 +35,6 @@ import (
|
|||
clientset "k8s.io/client-go/kubernetes"
|
||||
bootstrapapi "k8s.io/client-go/tools/bootstrap/token/api"
|
||||
bootstraputil "k8s.io/client-go/tools/bootstrap/token/util"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
clientcertutil "k8s.io/client-go/util/cert"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
|
@ -47,16 +42,11 @@ import (
|
|||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient"
|
||||
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/pubkeypin"
|
||||
tokenutil "k8s.io/kubernetes/cmd/kubeadm/app/util/token"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/printers"
|
||||
)
|
||||
|
||||
var joinCommandTemplate = template.Must(template.New("join").Parse(`` +
|
||||
`kubeadm join --token {{.Token}} {{.MasterHostPort}}{{range $h := .CAPubKeyPins}} --discovery-token-ca-cert-hash {{$h}}{{end}}`,
|
||||
))
|
||||
|
||||
// NewCmdToken returns cobra.Command for token management
|
||||
func NewCmdToken(out io.Writer, errW io.Writer) *cobra.Command {
|
||||
var kubeConfigFile string
|
||||
|
@ -247,7 +237,7 @@ func RunCreateToken(out io.Writer, client clientset.Interface, token string, tok
|
|||
// if --print-join-command was specified, print the full `kubeadm join` command
|
||||
// otherwise, just print the token
|
||||
if printJoinCommand {
|
||||
joinCommand, err := getJoinCommand(token, kubeConfigFile)
|
||||
joinCommand, err := cmdutil.GetJoinCommand(kubeConfigFile, token, false)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get join command: %v", err)
|
||||
}
|
||||
|
@ -395,52 +385,3 @@ func getClientset(file string, dryRun bool) (clientset.Interface, error) {
|
|||
}
|
||||
return kubeconfigutil.ClientSetFromFile(file)
|
||||
}
|
||||
|
||||
func getJoinCommand(token string, kubeConfigFile string) (string, error) {
|
||||
// load the kubeconfig file to get the CA certificate and endpoint
|
||||
config, err := clientcmd.LoadFromFile(kubeConfigFile)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to load kubeconfig: %v", err)
|
||||
}
|
||||
|
||||
// load the default cluster config
|
||||
clusterConfig := kubeconfigutil.GetClusterFromKubeConfig(config)
|
||||
if clusterConfig == nil {
|
||||
return "", fmt.Errorf("failed to get default cluster config")
|
||||
}
|
||||
|
||||
// load CA certificates from the kubeconfig (either from PEM data or by file path)
|
||||
var caCerts []*x509.Certificate
|
||||
if clusterConfig.CertificateAuthorityData != nil {
|
||||
caCerts, err = clientcertutil.ParseCertsPEM(clusterConfig.CertificateAuthorityData)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to parse CA certificate from kubeconfig: %v", err)
|
||||
}
|
||||
} else if clusterConfig.CertificateAuthority != "" {
|
||||
caCerts, err = clientcertutil.CertsFromFile(clusterConfig.CertificateAuthority)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to load CA certificate referenced by kubeconfig: %v", err)
|
||||
}
|
||||
} else {
|
||||
return "", fmt.Errorf("no CA certificates found in kubeconfig")
|
||||
}
|
||||
|
||||
// hash all the CA certs and include their public key pins as trusted values
|
||||
publicKeyPins := make([]string, 0, len(caCerts))
|
||||
for _, caCert := range caCerts {
|
||||
publicKeyPins = append(publicKeyPins, pubkeypin.Hash(caCert))
|
||||
}
|
||||
|
||||
ctx := map[string]interface{}{
|
||||
"Token": token,
|
||||
"CAPubKeyPins": publicKeyPins,
|
||||
"MasterHostPort": strings.Replace(clusterConfig.Server, "https://", "", -1),
|
||||
}
|
||||
|
||||
var out bytes.Buffer
|
||||
err = joinCommandTemplate.Execute(&out, ctx)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to render join command template: %v", err)
|
||||
}
|
||||
return out.String(), nil
|
||||
}
|
||||
|
|
|
@ -5,12 +5,17 @@ go_library(
|
|||
srcs = [
|
||||
"cmdutil.go",
|
||||
"documentation.go",
|
||||
"join.go",
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/util/kubeconfig:go_default_library",
|
||||
"//cmd/kubeadm/app/util/pubkeypin:go_default_library",
|
||||
"//pkg/util/normalizer:go_default_library",
|
||||
"//vendor/github.com/spf13/cobra:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/clientcmd:go_default_library",
|
||||
"//vendor/k8s.io/client-go/util/cert:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
Copyright 2018 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 util
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"strings"
|
||||
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
clientcertutil "k8s.io/client-go/util/cert"
|
||||
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/pubkeypin"
|
||||
)
|
||||
|
||||
var joinCommandTemplate = template.Must(template.New("join").Parse(`` +
|
||||
`kubeadm join {{.MasterHostPort}} --token {{.Token}}{{range $h := .CAPubKeyPins}} --discovery-token-ca-cert-hash {{$h}}{{end}}`,
|
||||
))
|
||||
|
||||
// GetJoinCommand returns the kubeadm join command for a given token and
|
||||
// and kubernetes cluster (the current cluster in the kubeconfig file)
|
||||
func GetJoinCommand(kubeConfigFile string, token string, skipTokenPrint bool) (string, error) {
|
||||
// load the kubeconfig file to get the CA certificate and endpoint
|
||||
config, err := clientcmd.LoadFromFile(kubeConfigFile)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to load kubeconfig: %v", err)
|
||||
}
|
||||
|
||||
// load the default cluster config
|
||||
clusterConfig := kubeconfigutil.GetClusterFromKubeConfig(config)
|
||||
if clusterConfig == nil {
|
||||
return "", fmt.Errorf("failed to get default cluster config")
|
||||
}
|
||||
|
||||
// load CA certificates from the kubeconfig (either from PEM data or by file path)
|
||||
var caCerts []*x509.Certificate
|
||||
if clusterConfig.CertificateAuthorityData != nil {
|
||||
caCerts, err = clientcertutil.ParseCertsPEM(clusterConfig.CertificateAuthorityData)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to parse CA certificate from kubeconfig: %v", err)
|
||||
}
|
||||
} else if clusterConfig.CertificateAuthority != "" {
|
||||
caCerts, err = clientcertutil.CertsFromFile(clusterConfig.CertificateAuthority)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to load CA certificate referenced by kubeconfig: %v", err)
|
||||
}
|
||||
} else {
|
||||
return "", fmt.Errorf("no CA certificates found in kubeconfig")
|
||||
}
|
||||
|
||||
// hash all the CA certs and include their public key pins as trusted values
|
||||
publicKeyPins := make([]string, 0, len(caCerts))
|
||||
for _, caCert := range caCerts {
|
||||
publicKeyPins = append(publicKeyPins, pubkeypin.Hash(caCert))
|
||||
}
|
||||
|
||||
ctx := map[string]interface{}{
|
||||
"Token": token,
|
||||
"CAPubKeyPins": publicKeyPins,
|
||||
"MasterHostPort": strings.Replace(clusterConfig.Server, "https://", "", -1),
|
||||
}
|
||||
|
||||
if skipTokenPrint {
|
||||
ctx["Token"] = template.HTML("<value withheld>")
|
||||
}
|
||||
|
||||
var out bytes.Buffer
|
||||
err = joinCommandTemplate.Execute(&out, ctx)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to render join command template: %v", err)
|
||||
}
|
||||
return out.String(), nil
|
||||
}
|
Loading…
Reference in New Issue