Skip to content

Commit 835373d

Browse files
feat: [DEVOPS-42674] support specify ssh endpoint (#3)
* feat: [DEVOPS-42674] support specify ssh endpoint * feat: [DEVOPS-42674] support specify ssh endpoint, optimize README.md
1 parent f2fd59a commit 835373d

File tree

6 files changed

+118
-11
lines changed

6 files changed

+118
-11
lines changed

README.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ make install
4040
# Set environment variables (optional)
4141
export GITLAB_URL=https://your-gitlab-instance.com
4242
export GITLAB_TOKEN=your-personal-access-token
43+
# Optional: SSH endpoint for clone/push templates
44+
export GITLAB_SSH_ENDPOINT=ssh://[email protected]:ssh-port
4345

4446
# Create user, groups, and projects
4547
./bin/gitlab-cli user create \
@@ -58,6 +60,7 @@ export GITLAB_TOKEN=your-personal-access-token
5860
./bin/gitlab-cli user create \
5961
--host https://your-gitlab.com \
6062
--token your-token \
63+
--ssh-endpoint ssh://[email protected]:ssh-port \
6164
-f config.yaml \
6265
-o output.yaml \
6366
-t template.yaml
@@ -216,6 +219,7 @@ token:
216219
```
217220

218221
Output contains all created resource information:
222+
- GitLab endpoint info: endpoint, scheme, host, port, ssh (endpoint/host/port when provided)
219223
- User info: username, email, name, user_id, password
220224
- Token info: value, scope, expires_at (if token is configured)
221225
- Group info: name, path, group_id, visibility (if groups are configured)
@@ -224,6 +228,14 @@ Output contains all created resource information:
224228
Output format:
225229

226230
```yaml
231+
endpoint: https://your-gitlab.com
232+
scheme: https
233+
host: your-gitlab.com
234+
port: 443
235+
ssh:
236+
endpoint: ssh://[email protected]:ssh-port
237+
host: your-gitlab.com
238+
port: ssh-port
227239
users:
228240
- username: tektoncd
229241
@@ -299,6 +311,12 @@ toolchains:
299311
endpoint: {{ $.Endpoint }}
300312
host: {{ $.Host }}
301313
scheme: {{ $.Scheme }}
314+
{{- if $.SSH }}
315+
ssh:
316+
endpoint: {{ $.SSH.Endpoint }}
317+
host: {{ $.SSH.Host }}
318+
port: {{ $.SSH.Port }}
319+
{{- end }}
302320
# User information
303321
username: {{ .Username }}
304322
email: {{ .Email }}
@@ -325,6 +343,7 @@ toolchains:
325343

326344
**Template Notes:**
327345
- `default: {{ .Username }}` - Specifies the default group, newly created projects will use this username as the namespace by default
346+
- `.SSH` is available when `--ssh-endpoint` or `GITLAB_SSH_ENDPOINT` is provided, useful for clone/push configs
328347

329348
Using the template:
330349

examples/template-example.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# GitLab CLI 输出模板示例
22
# 支持 Go template 语法,可以访问 OutputConfig 结构中的所有数据
33
# 数据结构: .Endpoint (完整 URL), .Scheme (http/https), .Host (主机名), .Port (端口号) 是 GitLab 服务器配置
4+
# Data: .SSH provides SSH endpoint, host and port when available
45
# 数据结构: .Users[0] 包含 Username, Email, Name, UserID, Password, Token, Groups, Projects
56

67
{{- range .Users }}
@@ -17,6 +18,12 @@ toolchains:
1718
port: {{ $.Port }}
1819
# scheme, http or https
1920
scheme: {{ $.Scheme }}
21+
{{- if $.SSH }}
22+
ssh:
23+
endpoint: {{ $.SSH.Endpoint }}
24+
host: {{ $.SSH.Host }}
25+
port: {{ $.SSH.Port }}
26+
{{- end }}
2027
# username, the user name of the login account
2128
username: {{ .Username }}
2229
# email

internal/cli/cmd.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package cli
33
import (
44
"fmt"
55
"log"
6+
"net/url"
67
"strconv"
78
"strings"
89
"time"
@@ -71,6 +72,7 @@ func buildUserCreateCommand(cfg *config.CLIConfig) *cobra.Command {
7172
cmd.Flags().StringVarP(&cfg.ConfigFile, "config", "f", "../test-users.yaml", "配置文件路径")
7273
cmd.Flags().StringVar(&cfg.GitLabHost, "host", "", "GitLab 主机地址")
7374
cmd.Flags().StringVar(&cfg.GitLabToken, "token", "", "GitLab Personal Access Token")
75+
cmd.Flags().StringVar(&cfg.GitLabSSHEndpoint, "ssh-endpoint", "", "GitLab SSH endpoint (e.g., ssh://git@host:22)")
7476
cmd.Flags().StringVarP(&cfg.OutputFile, "output", "o", "", "输出结果到 YAML 文件")
7577
cmd.Flags().StringVarP(&cfg.TemplateFile, "template", "t", "", "使用模板文件格式化输出")
7678

@@ -175,11 +177,25 @@ func runUserCreate(cfg *config.CLIConfig) error {
175177
// 从 GitLabHost 解析 endpoint、scheme、host 和 port
176178
endpoint, scheme, host, port := parseGitLabHostURL(cfg.GitLabHost)
177179

180+
// Parse SSH endpoint information for template rendering
181+
sshEndpoint, sshHost, sshPort := parseGitLabSSHEndpoint(cfg.GitLabSSHEndpoint)
182+
183+
// sshConfig holds parsed SSH endpoint details when available
184+
var sshConfig *types.SSHConfig
185+
if sshEndpoint != "" {
186+
sshConfig = &types.SSHConfig{
187+
Endpoint: sshEndpoint,
188+
Host: sshHost,
189+
Port: sshPort,
190+
}
191+
}
192+
178193
output := &types.OutputConfig{
179194
Endpoint: endpoint,
180195
Scheme: scheme,
181196
Host: host,
182197
Port: port,
198+
SSH: sshConfig,
183199
Users: userOutputs,
184200
}
185201

@@ -495,6 +511,51 @@ func initializeClient(cfg *config.CLIConfig) (*client.GitLabClient, error) {
495511
return gitlabClient, nil
496512
}
497513

514+
// parseGitLabSSHEndpoint extracts endpoint, host, and port from the SSH URL string
515+
func parseGitLabSSHEndpoint(rawEndpoint string) (endpoint, host string, port int) {
516+
// trimmedEndpoint stores the SSH endpoint without trailing slash or spaces
517+
trimmedEndpoint := strings.TrimSpace(rawEndpoint)
518+
if trimmedEndpoint == "" {
519+
return "", "", 0
520+
}
521+
522+
// normalizedEndpoint ensures the SSH URL includes a scheme for parsing
523+
normalizedEndpoint := strings.TrimSuffix(trimmedEndpoint, "/")
524+
if !strings.Contains(normalizedEndpoint, "://") {
525+
normalizedEndpoint = "ssh://" + normalizedEndpoint
526+
}
527+
528+
// parsedURL holds the parsed SSH URL result
529+
parsedURL, err := url.Parse(normalizedEndpoint)
530+
if err != nil {
531+
return normalizedEndpoint, "", 0
532+
}
533+
534+
// hostName captures the hostname portion of the SSH URL
535+
hostName := parsedURL.Hostname()
536+
// portNumber defaults to standard SSH port
537+
portNumber := 22
538+
if parsedURL.Port() != "" {
539+
if parsedPort, err := strconv.Atoi(parsedURL.Port()); err == nil {
540+
portNumber = parsedPort
541+
} else {
542+
portNumber = 0
543+
}
544+
}
545+
546+
// endpointBuilder rebuilds the endpoint including user info when available
547+
endpointBuilder := parsedURL.Scheme + "://"
548+
if parsedURL.User != nil {
549+
endpointBuilder += parsedURL.User.String() + "@"
550+
}
551+
endpointBuilder += hostName
552+
if portNumber > 0 {
553+
endpointBuilder += ":" + strconv.Itoa(portNumber)
554+
}
555+
556+
return endpointBuilder, hostName, portNumber
557+
}
558+
498559
// parseGitLabHostURL 从 GitLab Host URL 解析出 endpoint、scheme 和 host
499560
func parseGitLabHostURL(gitlabHost string) (endpoint, scheme, host string, port int) {
500561
// 默认值

internal/config/config.go

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,13 @@ import (
1010

1111
// CLIConfig 封装CLI配置参数
1212
type CLIConfig struct {
13-
ConfigFile string
14-
GitLabHost string
15-
GitLabToken string
16-
OutputFile string // 输出文件路径
17-
TemplateFile string // 模板文件路径
18-
DaysOld int // 只删除创建日期超过指定天数的用户(cleanup 命令使用)
13+
ConfigFile string
14+
GitLabHost string
15+
GitLabToken string
16+
OutputFile string // 输出文件路径
17+
TemplateFile string // 模板文件路径
18+
DaysOld int // 只删除创建日期超过指定天数的用户(cleanup 命令使用)
19+
GitLabSSHEndpoint string // GitLab SSH endpoint (e.g., ssh://git@host:22)
1920
}
2021

2122
// LoadGitLabCredentials 从环境变量或命令行参数加载 GitLab 凭证
@@ -32,6 +33,10 @@ func LoadGitLabCredentials(cfg *CLIConfig) error {
3233
return fmt.Errorf("GitLab token is required (use --token or GITLAB_TOKEN env)")
3334
}
3435
}
36+
// Populate SSH endpoint from environment when flag is not provided
37+
if cfg.GitLabSSHEndpoint == "" {
38+
cfg.GitLabSSHEndpoint = os.Getenv("GITLAB_SSH_ENDPOINT")
39+
}
3540
return nil
3641
}
3742

pkg/types/types.go

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,21 @@ type ProjectSpec struct {
4545
// 输出结果类型
4646
// ========================================
4747

48+
// SSHConfig captures parsed SSH endpoint information
49+
type SSHConfig struct {
50+
Endpoint string `yaml:"endpoint"` // Endpoint is the normalized SSH endpoint string
51+
Host string `yaml:"host"` // Host is the SSH hostname extracted from the endpoint
52+
Port int `yaml:"port"` // Port is the SSH port number
53+
}
54+
4855
// OutputConfig 输出配置结构
4956
type OutputConfig struct {
50-
Endpoint string `yaml:"endpoint"`
51-
Scheme string `yaml:"scheme"`
52-
Host string `yaml:"host"`
53-
Port int `yaml:"port"`
54-
Users []UserOutput `yaml:"users"`
57+
Endpoint string `yaml:"endpoint"` // Endpoint is the normalized HTTP endpoint of GitLab
58+
Scheme string `yaml:"scheme"` // Scheme is the HTTP scheme of the GitLab endpoint
59+
Host string `yaml:"host"` // Host is the hostname of the GitLab endpoint
60+
Port int `yaml:"port"` // Port is the HTTP port of the GitLab endpoint
61+
SSH *SSHConfig `yaml:"ssh,omitempty"` // SSH holds parsed SSH endpoint details when available
62+
Users []UserOutput `yaml:"users"` // Users carries all generated user outputs
5563
}
5664

5765
// UserOutput 用户输出结果

template-example.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# GitLab CLI 输出模板示例
22
# 支持 Go template 语法,可以访问 OutputConfig 结构中的所有数据
33
# 数据结构: .Endpoint (完整 URL), .Scheme (http/https), .Host (主机名) 是 GitLab 服务器配置
4+
# Data: .SSH provides SSH endpoint, host and port when available
45
# 数据结构: .Users[0] 包含 Username, Email, Name, UserID, Token, Groups
56

67
{{- range .Users }}
@@ -15,6 +16,12 @@ toolchains:
1516
host: {{ $.Host }}
1617
# scheme, http or https
1718
scheme: {{ $.Scheme }}
19+
{{- if $.SSH }}
20+
ssh:
21+
endpoint: {{ $.SSH.Endpoint }}
22+
host: {{ $.SSH.Host }}
23+
port: {{ $.SSH.Port }}
24+
{{- end }}
1825
# username, the user name of the login account
1926
username: {{ .Username }}
2027
# email

0 commit comments

Comments
 (0)