|
1 | 1 | package cmd |
2 | 2 |
|
3 | 3 | import ( |
| 4 | + "bufio" |
4 | 5 | "os" |
| 6 | + "strconv" |
| 7 | + "strings" |
5 | 8 |
|
6 | 9 | "github.com/creasty/defaults" |
7 | 10 | "github.com/k0sproject/dig" |
@@ -80,40 +83,159 @@ telemetry: |
80 | 83 | enabled: true |
81 | 84 | `) |
82 | 85 |
|
| 86 | +var defaultHosts = cluster.Hosts{ |
| 87 | + &cluster.Host{ |
| 88 | + Connection: rig.Connection{ |
| 89 | + SSH: &rig.SSH{ |
| 90 | + Address: "10.0.0.1", |
| 91 | + }, |
| 92 | + }, |
| 93 | + Role: "controller", |
| 94 | + }, |
| 95 | + &cluster.Host{ |
| 96 | + Connection: rig.Connection{ |
| 97 | + SSH: &rig.SSH{ |
| 98 | + Address: "10.0.0.2", |
| 99 | + }, |
| 100 | + }, |
| 101 | + Role: "worker", |
| 102 | + }, |
| 103 | +} |
| 104 | + |
| 105 | +func hostFromAddress(addr, role, user, keypath string) *cluster.Host { |
| 106 | + port := 22 |
| 107 | + |
| 108 | + if idx := strings.Index(addr, "@"); idx > 0 { |
| 109 | + user = addr[:idx] |
| 110 | + addr = addr[idx+1:] |
| 111 | + } |
| 112 | + |
| 113 | + if idx := strings.Index(addr, ":"); idx > 0 { |
| 114 | + pstr := addr[idx+1:] |
| 115 | + if p, err := strconv.Atoi(pstr); err == nil { |
| 116 | + port = p |
| 117 | + } |
| 118 | + addr = addr[:idx] |
| 119 | + } |
| 120 | + |
| 121 | + host := &cluster.Host{ |
| 122 | + Connection: rig.Connection{ |
| 123 | + SSH: &rig.SSH{ |
| 124 | + Address: addr, |
| 125 | + Port: port, |
| 126 | + }, |
| 127 | + }, |
| 128 | + } |
| 129 | + if role != "" { |
| 130 | + host.Role = role |
| 131 | + } else { |
| 132 | + host.Role = "worker" |
| 133 | + } |
| 134 | + if user != "" { |
| 135 | + host.SSH.User = user |
| 136 | + } |
| 137 | + if keypath != "" { |
| 138 | + host.SSH.KeyPath = keypath |
| 139 | + } |
| 140 | + |
| 141 | + _ = defaults.Set(host) |
| 142 | + |
| 143 | + return host |
| 144 | +} |
| 145 | + |
| 146 | +func buildHosts(addresses []string, ccount int, user, keypath string) cluster.Hosts { |
| 147 | + var hosts cluster.Hosts |
| 148 | + role := "controller" |
| 149 | + for _, a := range addresses { |
| 150 | + // strip trailing comments |
| 151 | + if idx := strings.Index(a, "#"); idx > 0 { |
| 152 | + a = a[:idx] |
| 153 | + } |
| 154 | + a = strings.TrimSpace(a) |
| 155 | + if a == "" || strings.HasPrefix(a, "#") { |
| 156 | + // skip empty and comment lines |
| 157 | + continue |
| 158 | + } |
| 159 | + |
| 160 | + if len(hosts) >= ccount { |
| 161 | + role = "worker" |
| 162 | + } |
| 163 | + |
| 164 | + hosts = append(hosts, hostFromAddress(a, role, user, keypath)) |
| 165 | + } |
| 166 | + |
| 167 | + if len(hosts) == 0 { |
| 168 | + return defaultHosts |
| 169 | + } |
| 170 | + |
| 171 | + return hosts |
| 172 | +} |
| 173 | + |
83 | 174 | var initCommand = &cli.Command{ |
84 | | - Name: "init", |
85 | | - Usage: "Create a configuration template", |
| 175 | + Name: "init", |
| 176 | + Usage: "Create a configuration template", |
| 177 | + Description: "Outputs a new k0sctl configuration. When a list of addresses are provided, hosts are generated into the configuration. The list of addresses can also be provided via stdin.", |
| 178 | + ArgsUsage: "[[user@]address[:port] ...]", |
86 | 179 | Flags: []cli.Flag{ |
87 | 180 | &cli.BoolFlag{ |
88 | 181 | Name: "k0s", |
89 | 182 | Usage: "Include a skeleton k0s config section", |
90 | 183 | }, |
| 184 | + &cli.StringFlag{ |
| 185 | + Name: "cluster-name", |
| 186 | + Usage: "Cluster name", |
| 187 | + Aliases: []string{"n"}, |
| 188 | + Value: "k0s-cluster", |
| 189 | + }, |
| 190 | + &cli.IntFlag{ |
| 191 | + Name: "controller-count", |
| 192 | + Usage: "The number of controllers to create when addresses are given", |
| 193 | + Aliases: []string{"C"}, |
| 194 | + Value: 1, |
| 195 | + }, |
| 196 | + &cli.StringFlag{ |
| 197 | + Name: "user", |
| 198 | + Usage: "Host user when addresses given", |
| 199 | + Aliases: []string{"u"}, |
| 200 | + }, |
| 201 | + &cli.StringFlag{ |
| 202 | + Name: "key-path", |
| 203 | + Usage: "Host key path when addresses given", |
| 204 | + Aliases: []string{"i"}, |
| 205 | + }, |
91 | 206 | }, |
92 | 207 | Action: func(ctx *cli.Context) error { |
| 208 | + var addresses []string |
| 209 | + |
| 210 | + // Read addresses from stdin |
| 211 | + stat, err := os.Stdin.Stat() |
| 212 | + if err == nil { |
| 213 | + if (stat.Mode() & os.ModeCharDevice) == 0 { |
| 214 | + rd := bufio.NewReader(os.Stdin) |
| 215 | + for { |
| 216 | + row, _, err := rd.ReadLine() |
| 217 | + if err != nil { |
| 218 | + break |
| 219 | + } |
| 220 | + addresses = append(addresses, string(row)) |
| 221 | + } |
| 222 | + if err != nil { |
| 223 | + return err |
| 224 | + } |
| 225 | + |
| 226 | + } |
| 227 | + } |
| 228 | + |
| 229 | + // Read addresses from args |
| 230 | + addresses = append(addresses, ctx.Args().Slice()...) |
| 231 | + |
93 | 232 | cfg := config.Cluster{ |
94 | 233 | APIVersion: config.APIVersion, |
95 | 234 | Kind: "Cluster", |
96 | | - Metadata: &config.ClusterMetadata{}, |
| 235 | + Metadata: &config.ClusterMetadata{Name: ctx.String("cluster-name")}, |
97 | 236 | Spec: &cluster.Spec{ |
98 | | - Hosts: cluster.Hosts{ |
99 | | - &cluster.Host{ |
100 | | - Connection: rig.Connection{ |
101 | | - SSH: &rig.SSH{ |
102 | | - Address: "10.0.0.1", |
103 | | - }, |
104 | | - }, |
105 | | - Role: "controller", |
106 | | - }, |
107 | | - &cluster.Host{ |
108 | | - Connection: rig.Connection{ |
109 | | - SSH: &rig.SSH{ |
110 | | - Address: "10.0.0.2", |
111 | | - }, |
112 | | - }, |
113 | | - Role: "worker", |
114 | | - }, |
115 | | - }, |
116 | | - K0s: cluster.K0s{}, |
| 237 | + Hosts: buildHosts(addresses, ctx.Int("controller-count"), ctx.String("user"), ctx.String("key-path")), |
| 238 | + K0s: cluster.K0s{}, |
117 | 239 | }, |
118 | 240 | } |
119 | 241 |
|
|
0 commit comments