Skip to content

Commit

Permalink
Use proper URLs for initial-advertise-peer-urls & advertise-client-ur…
Browse files Browse the repository at this point in the history
…ls instead of @ separator
  • Loading branch information
anveshreddy18 committed Oct 8, 2024
1 parent 52c0e74 commit 93fe1ca
Show file tree
Hide file tree
Showing 7 changed files with 372 additions and 103 deletions.
25 changes: 6 additions & 19 deletions pkg/member/member_control.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,9 @@ func NewMemberControl(etcdConnConfig *brtypes.EtcdConnectionConfig) Control {
// AddMemberAsLearner add a member as a learner to the etcd cluster
func (m *memberControl) AddMemberAsLearner(ctx context.Context) error {
//Add member as learner to cluster
memberURL, err := getMemberPeerURL(m.configFile, m.podName)
// TODO: Need to handle multiple peer URLs once etcd config is updated to support it.
// It is required in the context of Gardener usecase to support live control plane migration.
memberURL, err := miscellaneous.GetAdvertisePeerURLs(m.configFile)
if err != nil {
m.logger.Fatalf("Error fetching etcd member URL : %v", err)
}
Expand Down Expand Up @@ -198,28 +200,13 @@ func (m *memberControl) IsMemberInCluster(ctx context.Context) (bool, error) {
return false, nil
}

func getMemberPeerURL(configFile string, podName string) (string, error) {
config, err := miscellaneous.ReadConfigFileAsMap(configFile)
if err != nil {
return "", err
}
initAdPeerURL := config["initial-advertise-peer-urls"]
if initAdPeerURL == nil {
return "", errors.New("initial-advertise-peer-urls must be set in etcd config")
}
peerURL, err := miscellaneous.ParsePeerURL(initAdPeerURL.(string), podName)
if err != nil {
return "", fmt.Errorf("could not parse peer URL from the config file : %v", err)
}
return peerURL, nil
}

// doUpdateMemberPeerAddress updated the peer address of a specified etcd member
func (m *memberControl) doUpdateMemberPeerAddress(ctx context.Context, cli etcdClient.ClusterCloser, id uint64) error {
// Already existing clusters or cluster after restoration have `http://localhost:2380` as the peer address. This needs to explicitly updated to the correct peer address.
m.logger.Infof("Updating member peer URL for %s", m.podName)

memberPeerURL, err := getMemberPeerURL(m.configFile, m.podName)
// TODO: Need to handle multiple peer URLs once etcd config is updated to support it.
// It is required in the context of Gardener usecase to support live control plane migration.
memberPeerURL, err := miscellaneous.GetAdvertisePeerURLs(m.configFile)
if err != nil {
return fmt.Errorf("could not fetch member URL : %v", err)
}
Expand Down
31 changes: 17 additions & 14 deletions pkg/member/member_control_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,20 +47,23 @@ var _ = Describe("Membercontrol", func() {

outfile := "/tmp/etcd.conf.yaml"
etcdConfigYaml := `# Human-readable name for this member.
name: etcd1
data-dir: ` + os.Getenv("ETCD_DATA_DIR") + `
metrics: extensive
snapshot-count: 75000
enable-v2: false
quota-backend-bytes: 1073741824
listen-client-urls: http://0.0.0.0:2379
advertise-client-urls: http://0.0.0.0:2379
initial-advertise-peer-urls: http@etcd-main-peer@default@2380
initial-cluster: etcd1=http://0.0.0.0:2380
initial-cluster-token: new
initial-cluster-state: new
auto-compaction-mode: periodic
auto-compaction-retention: 30m`
name: etcd1
data-dir: ` + os.Getenv("ETCD_DATA_DIR") + `
metrics: extensive
snapshot-count: 75000
enable-v2: false
quota-backend-bytes: 1073741824
listen-client-urls: http://0.0.0.0:2379
advertise-client-urls:
` + podName + `: http://0.0.0.0:2379
initial-advertise-peer-urls:
` + podName + `:
- http://etcd-main-peer.default:2380
initial-cluster: etcd1=http://0.0.0.0:2380
initial-cluster-token: new
initial-cluster-state: new
auto-compaction-mode: periodic
auto-compaction-retention: 30m`

err := os.WriteFile(outfile, []byte(etcdConfigYaml), 0755)
Expect(err).ShouldNot(HaveOccurred())
Expand Down
97 changes: 78 additions & 19 deletions pkg/miscellaneous/miscellaneous.go
Original file line number Diff line number Diff line change
Expand Up @@ -529,41 +529,100 @@ func ReadConfigFileAsMap(path string) (map[string]interface{}, error) {
return c, nil
}

// ParsePeerURL forms a PeerURL, given podName by parsing the initial-advertise-peer-urls
func ParsePeerURL(initialAdvertisePeerURLs, podName string) (string, error) {
tokens := strings.Split(initialAdvertisePeerURLs, "@")
if len(tokens) < 4 {
return "", fmt.Errorf("invalid peer URL : %s", initialAdvertisePeerURLs)
// GetAdvertisePeerURLs returns the advertise peer URLs for the etcd member.
func GetAdvertisePeerURLs(configFile string) (string, error) {
memberName, err := GetEnvVarOrError("POD_NAME")
if err != nil {
return "", err
}
domaiName := fmt.Sprintf("%s.%s.%s", tokens[1], tokens[2], "svc")
return fmt.Sprintf("%s://%s.%s:%s", tokens[0], podName, domaiName, tokens[3]), nil
}

// IsPeerURLTLSEnabled checks whether the peer address is TLS enabled or not.
func IsPeerURLTLSEnabled() (bool, error) {
podName, err := GetEnvVarOrError("POD_NAME")
config, err := ReadConfigFileAsMap(configFile)
if err != nil {
return false, err
return "", err
}
initAdPeerURL := config["initial-advertise-peer-urls"]
if initAdPeerURL == nil {
return "", fmt.Errorf("initial-advertise-peer-urls must be set in etcd config")
}

configFile := GetConfigFilePath()
peerUrlsMap, ok := initAdPeerURL.(map[interface{}]interface{})
if !ok {
return "", fmt.Errorf("initial-advertise-peer-urls is not in the expected format")
}
resultMap := make(map[string][]string)
for pod, urls := range peerUrlsMap {
podName, ok := pod.(string)
if !ok {
return "", fmt.Errorf("pod name is not a string")
}
urlsList, ok := urls.([]interface{})
if !ok {
return "", fmt.Errorf("urls is not a list")
}
for _, url := range urlsList {
urlStr, ok := url.(string)
if !ok {
return "", fmt.Errorf("url is not a string")
}
resultMap[podName] = append(resultMap[podName], urlStr)
}
}
peerUrls, ok := resultMap[memberName]
if !ok {
return "", fmt.Errorf("peer url not found for pod %s", memberName)
}
return strings.Join(peerUrls, ","), nil
}

// GetAdvertiseClientURL returns the advertise client URL for the etcd member.
func GetAdvertiseClientURL(configFile string) (string, error) {
memberName, err := GetEnvVarOrError("POD_NAME")
if err != nil {
return "", err
}
config, err := ReadConfigFileAsMap(configFile)
if err != nil {
return false, err
return "", err
}
initAdPeerURL := config["initial-advertise-peer-urls"]
initAdClientURL := config["advertise-client-urls"]
if initAdClientURL == nil {
return "", fmt.Errorf("advertise-client-urls must be set in etcd config")
}
clientUrlsMap, ok := initAdClientURL.(map[interface{}]interface{})
if !ok {
return "", fmt.Errorf("advertise-client-urls is not in the expected format")
}
resultMap := make(map[string]string)
for pod, url := range clientUrlsMap {
podName, ok := pod.(string)
if !ok {
return "", fmt.Errorf("pod name is not a string")
}
urlStr, ok := url.(string)
if !ok {
return "", fmt.Errorf("url is not a string")
}
resultMap[podName] = urlStr
}
clientURL, ok := resultMap[memberName]
if !ok {
return "", fmt.Errorf("client url not found for pod %s", memberName)
}
return clientURL, nil
}

memberPeerURL, err := ParsePeerURL(initAdPeerURL.(string), podName)
// IsPeerURLTLSEnabled checks whether the peer address is TLS enabled or not.
func IsPeerURLTLSEnabled() (bool, error) {
configFile := GetConfigFilePath()
// TODO: Need to handle multiple peer URLs once etcd config is updated to support it.
// It is required in the context of Gardener usecase to support live control plane migration.
memberPeerURL, err := GetAdvertisePeerURLs(configFile)
if err != nil {
return false, err
}

peerURL, err := url.Parse(memberPeerURL)
if err != nil {
return false, err
}

return peerURL.Scheme == https, nil
}

Expand Down
Loading

0 comments on commit 93fe1ca

Please sign in to comment.