Skip to content

Commit

Permalink
add yurtadm join node in specified nodepool (#1402)
Browse files Browse the repository at this point in the history
* add yurtadm join node in specified nodepool
  • Loading branch information
JameKeal authored Jun 13, 2023
1 parent 70e53a9 commit 731b71e
Show file tree
Hide file tree
Showing 11 changed files with 202 additions and 1 deletion.
3 changes: 3 additions & 0 deletions charts/yurthub/templates/yurthub-cloud-yurtstaticset.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ spec:
{{- if .Values.organizations }}
- --hub-cert-organizations={{ .Values.organizations }}
{{- end }}
{{- if .nodePoolName }}
- --nodepool-name={{ .Values.nodePoolName }}
{{- end }}
livenessProbe:
httpGet:
host: {{ .Values.yurthubBindingAddr }}
Expand Down
3 changes: 3 additions & 0 deletions charts/yurthub/templates/yurthub-yurtstaticset.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ spec:
{{- if .Values.organizations }}
- --hub-cert-organizations={{ .Values.organizations }}
{{- end }}
{{- if .nodePoolName }}
- --nodepool-name={{ .Values.nodePoolName }}
{{- end }}
livenessProbe:
httpGet:
host: {{ .Values.yurthubBindingAddr }}
Expand Down
17 changes: 17 additions & 0 deletions pkg/util/kubeconfig/kubeconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import (
clientset "k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"

yurtclientset "github.com/openyurtio/yurt-app-manager-api/pkg/yurtappmanager/client/clientset/versioned"
)

// CreateBasic creates a basic, general KubeConfig object that then can be extended
Expand Down Expand Up @@ -125,3 +127,18 @@ func GetAuthInfoFromKubeConfig(config *clientcmdapi.Config) *clientcmdapi.AuthIn
}
return nil
}

// ToYurtClientSet converts a KubeConfig object to a yurtClient
func ToYurtClientSet(config *clientcmdapi.Config) (yurtclientset.Interface, error) {
overrides := clientcmd.ConfigOverrides{Timeout: "10s"}
clientConfig, err := clientcmd.NewDefaultClientConfig(*config, &overrides).ClientConfig()
if err != nil {
return nil, errors.Wrap(err, "failed to create yurt client configuration from kubeconfig")
}

client, err := yurtclientset.NewForConfig(clientConfig)
if err != nil {
return nil, errors.Wrap(err, "failed to create yurt client")
}
return client, nil
}
2 changes: 2 additions & 0 deletions pkg/util/kubeconfig/kubeconfig_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,8 @@ func TestWriteKubeconfigToDisk(t *testing.T) {
newFile,
)
}
client, err := ToYurtClientSet(c)
t.Log(client, err)
})
}
}
23 changes: 23 additions & 0 deletions pkg/util/kubernetes/kubeadm/app/util/apiclient/idempotency.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ import (
clientsetretry "k8s.io/client-go/util/retry"

"github.com/openyurtio/openyurt/pkg/util/kubernetes/kubeadm/app/constants"
nodepoolv1alpha1 "github.com/openyurtio/yurt-app-manager-api/pkg/yurtappmanager/apis/apps/v1alpha1"
yurtclientset "github.com/openyurtio/yurt-app-manager-api/pkg/yurtappmanager/client/clientset/versioned"
)

// ConfigMapMutator is a function that mutates the given ConfigMap and optionally returns an error
Expand Down Expand Up @@ -131,3 +133,24 @@ func GetConfigMapWithRetry(client clientset.Interface, namespace, name string) (
}
return nil, lastError
}

func GetNodePoolInfoWithRetry(client yurtclientset.Interface, name string) (*nodepoolv1alpha1.NodePool, error) {
var np *nodepoolv1alpha1.NodePool
var lastError error
err := wait.ExponentialBackoff(clientsetretry.DefaultBackoff, func() (bool, error) {
var err error
np, err = client.AppsV1alpha1().NodePools().Get(context.TODO(), name, metav1.GetOptions{})
if err == nil {
return true, nil
}
if apierrors.IsNotFound(err) {
return true, nil
}
lastError = err
return false, nil
})
if err == nil {
return np, nil
}
return nil, lastError
}
25 changes: 25 additions & 0 deletions pkg/yurtadm/cmd/join/join.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,20 @@ import (

"github.com/openyurtio/openyurt/pkg/controller/yurtstaticset/util"
kubeconfigutil "github.com/openyurtio/openyurt/pkg/util/kubeconfig"
"github.com/openyurtio/openyurt/pkg/util/kubernetes/kubeadm/app/util/apiclient"
"github.com/openyurtio/openyurt/pkg/yurtadm/cmd/join/joindata"
yurtphases "github.com/openyurtio/openyurt/pkg/yurtadm/cmd/join/phases"
yurtconstants "github.com/openyurtio/openyurt/pkg/yurtadm/constants"
"github.com/openyurtio/openyurt/pkg/yurtadm/util/edgenode"
yurtadmutil "github.com/openyurtio/openyurt/pkg/yurtadm/util/kubernetes"
nodepoolv1alpha1 "github.com/openyurtio/yurt-app-manager-api/pkg/yurtappmanager/apis/apps/v1alpha1"
)

type joinOptions struct {
token string
nodeType string
nodeName string
nodePoolName string
criSocket string
organizations string
pauseImage string
Expand Down Expand Up @@ -125,6 +128,10 @@ func addJoinConfigFlags(flagSet *flag.FlagSet, joinOptions *joinOptions) {
&joinOptions.namespace, yurtconstants.Namespace, joinOptions.namespace,
`Specify the namespace of the yurthub staticpod configmap, if not specified, the namespace will be default.`,
)
flagSet.StringVar(
&joinOptions.nodePoolName, yurtconstants.NodePoolName, joinOptions.nodePoolName,
`Specify the nodePool name. if specified, that will add node into specified nodePool.`,
)
flagSet.StringVar(
&joinOptions.criSocket, yurtconstants.NodeCRISocket, joinOptions.criSocket,
"Path to the CRI socket to connect",
Expand Down Expand Up @@ -276,6 +283,7 @@ func newJoinData(args []string, opt *joinOptions) (*joinData, error) {
nodeLabels: make(map[string]string),
joinNodeData: &joindata.NodeRegistration{
Name: name,
NodePoolName: opt.nodePoolName,
WorkingMode: opt.nodeType,
CRISocket: opt.criSocket,
Organizations: opt.organizations,
Expand Down Expand Up @@ -320,6 +328,23 @@ func newJoinData(args []string, opt *joinOptions) (*joinData, error) {
return nil, err
}
data.kubernetesVersion = k8sVersion

// check whether specified nodePool exists
if len(opt.nodePoolName) != 0 {
yurtClient, err := kubeconfigutil.ToYurtClientSet(cfg)
if err != nil {
klog.Errorf("failed to create yurt client, %v", err)
return nil, err
}

np, err := apiclient.GetNodePoolInfoWithRetry(yurtClient, opt.nodePoolName)
if err != nil || np == nil {
// the specified nodePool not exist, return
return nil, errors.Errorf("when --nodepool-name is specified, the specified nodePool should be exist.")
}
// add nodePool label for node by kubelet
data.nodeLabels[nodepoolv1alpha1.LabelDesiredNodePool] = opt.nodePoolName
}
klog.Infof("node join data info: %#+v", *data)

// get the yurthub template from the staticpod cr
Expand Down
12 changes: 11 additions & 1 deletion pkg/yurtadm/cmd/join/join_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,10 @@ func TestRun(t *testing.T) {

func TestNewJoinData(t *testing.T) {
jo := newJoinOptions()
jo2 := newJoinOptions()
jo2.token = "v22u0b.17490yh3xp8azpr0"
jo2.unsafeSkipCAVerification = true
jo2.nodePoolName = "nodePool2"

tests := []struct {
name string
Expand All @@ -244,10 +248,16 @@ func TestNewJoinData(t *testing.T) {
}{
{
"normal",
[]string{},
[]string{"localhost:8080"},
jo,
nil,
},
{
"norma2",
[]string{"localhost:8080"},
jo2,
nil,
},
}

for _, tt := range tests {
Expand Down
1 change: 1 addition & 0 deletions pkg/yurtadm/cmd/join/joindata/data.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (

type NodeRegistration struct {
Name string
NodePoolName string
CRISocket string
WorkingMode string
Organizations string
Expand Down
5 changes: 5 additions & 0 deletions pkg/yurtadm/constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ const (
NodeLabels = "node-labels"
// NodeName flag sets the node name.
NodeName = "node-name"
// NodePoolName flag sets the nodePool name.
NodePoolName = "nodepool-name"
// NodeType flag sets the type of worker node to edge or cloud.
NodeType = "node-type"
// Organizations flag sets the extra organizations of hub agent client certificate.
Expand Down Expand Up @@ -234,6 +236,9 @@ spec:
{{if .organizations }}
- --hub-cert-organizations={{.organizations}}
{{end}}
{{if .nodePoolName }}
- --nodepool-name={{.nodePoolName}}
{{end}}
livenessProbe:
httpGet:
host: {{.yurthubBindingAddr}}
Expand Down
3 changes: 3 additions & 0 deletions pkg/yurtadm/util/yurthub/yurthub.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ func AddYurthubStaticYaml(data joindata.YurtJoinData, podManifestPath string) er
"namespace": data.Namespace(),
"image": data.YurtHubImage(),
}
if len(data.NodeRegistration().NodePoolName) != 0 {
ctx["nodePoolName"] = data.NodeRegistration().NodePoolName
}

yurthubTemplate, err := templates.SubsituteTemplate(data.YurtHubTemplate(), ctx)
if err != nil {
Expand Down
109 changes: 109 additions & 0 deletions pkg/yurtadm/util/yurthub/yurthub_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ import (
"testing"

"github.com/stretchr/testify/assert"
"k8s.io/apimachinery/pkg/util/sets"
clientset "k8s.io/client-go/kubernetes"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"

"github.com/openyurtio/openyurt/pkg/yurtadm/cmd/join/joindata"
)

var (
Expand Down Expand Up @@ -225,3 +230,107 @@ func Test_useRealServerAddr(t *testing.T) {
})
}
}

type testData struct {
joinNodeData *joindata.NodeRegistration
}

func (j *testData) ServerAddr() string {
return ""
}

func (j *testData) JoinToken() string {
return ""
}

func (j *testData) PauseImage() string {
return ""
}

func (j *testData) YurtHubImage() string {
return ""
}

func (j *testData) YurtHubServer() string {
return ""
}

func (j *testData) YurtHubTemplate() string {
return ""
}

func (j *testData) YurtHubManifest() string {
return ""
}

func (j *testData) KubernetesVersion() string {
return ""
}

func (j *testData) TLSBootstrapCfg() *clientcmdapi.Config {
return nil
}

func (j *testData) BootstrapClient() *clientset.Clientset {
return nil
}

func (j *testData) NodeRegistration() *joindata.NodeRegistration {
return j.joinNodeData
}

func (j *testData) IgnorePreflightErrors() sets.String {
return nil
}

func (j *testData) CaCertHashes() []string {
return nil
}

func (j *testData) NodeLabels() map[string]string {
return nil
}

func (j *testData) KubernetesResourceServer() string {
return ""
}

func (j *testData) ReuseCNIBin() bool {
return false
}

func (j *testData) Namespace() string {
return ""
}

func TestAddYurthubStaticYaml(t *testing.T) {
xdata := testData{
joinNodeData: &joindata.NodeRegistration{
Name: "name1",
NodePoolName: "nodePool1",
CRISocket: "",
WorkingMode: "edge",
Organizations: "",
}}

tests := []struct {
name string
data testData
podManifestPath string
wantErr bool
}{
{
name: "test",
data: xdata,
podManifestPath: "/tmp",
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := AddYurthubStaticYaml(&tt.data, tt.podManifestPath); (err != nil) != tt.wantErr {
t.Errorf("AddYurthubStaticYaml() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}

0 comments on commit 731b71e

Please sign in to comment.