mirror of
https://github.com/siderolabs/talos.git
synced 2025-10-14 00:51:12 +02:00
feat: change UI component for disks selector
Implemented a new component based on `tview.Table` that shows all available block devices as a table. Had to stop using standard form control, because it doesn't really handle multiline elements. Signed-off-by: Artem Chernyshev <artem.0xD2@gmail.com>
This commit is contained in:
parent
dd810d0514
commit
07b7a8c103
76
internal/pkg/tui/components/form.go
Normal file
76
internal/pkg/tui/components/form.go
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
package components
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gdamore/tcell/v2"
|
||||||
|
"github.com/rivo/tview"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewForm creates a new form.
|
||||||
|
func NewForm() *Form {
|
||||||
|
return &Form{
|
||||||
|
Flex: tview.NewFlex().SetDirection(tview.FlexRow),
|
||||||
|
formItems: []tview.FormItem{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Form is a more flexible form component for tview lib.
|
||||||
|
type Form struct {
|
||||||
|
*tview.Flex
|
||||||
|
formItems []tview.FormItem
|
||||||
|
maxLabelLen int
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddFormItem adds a new item to the form.
|
||||||
|
func (f *Form) AddFormItem(item tview.Primitive) {
|
||||||
|
if formItem, ok := item.(tview.FormItem); ok {
|
||||||
|
f.formItems = append(f.formItems, formItem)
|
||||||
|
labelLen := len(formItem.GetLabel()) + 1
|
||||||
|
|
||||||
|
if labelLen > f.maxLabelLen {
|
||||||
|
for _, item := range f.formItems[:len(f.formItems)-1] {
|
||||||
|
item.SetFormAttributes(
|
||||||
|
labelLen,
|
||||||
|
tview.Styles.PrimaryTextColor,
|
||||||
|
f.GetBackgroundColor(),
|
||||||
|
tview.Styles.PrimaryTextColor,
|
||||||
|
tview.Styles.ContrastBackgroundColor,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
f.maxLabelLen = labelLen
|
||||||
|
}
|
||||||
|
|
||||||
|
formItem.SetFormAttributes(
|
||||||
|
f.maxLabelLen,
|
||||||
|
tview.Styles.PrimaryTextColor,
|
||||||
|
f.GetBackgroundColor(),
|
||||||
|
tview.Styles.PrimaryTextColor,
|
||||||
|
tview.Styles.ContrastBackgroundColor,
|
||||||
|
)
|
||||||
|
} else if box, ok := item.(Box); ok {
|
||||||
|
box.SetBackgroundColor(f.GetBackgroundColor())
|
||||||
|
}
|
||||||
|
|
||||||
|
height := 1
|
||||||
|
multiline, ok := item.(Multiline)
|
||||||
|
|
||||||
|
if ok {
|
||||||
|
height = multiline.GetHeight()
|
||||||
|
}
|
||||||
|
|
||||||
|
f.AddItem(item, height+1, 1, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Multiline interface represents elements that can occupy more than one line.
|
||||||
|
type Multiline interface {
|
||||||
|
GetHeight() int
|
||||||
|
}
|
||||||
|
|
||||||
|
// Box interface that has just SetBackgroundColor.
|
||||||
|
type Box interface {
|
||||||
|
SetBackgroundColor(tcell.Color) *tview.Box
|
||||||
|
}
|
@ -5,7 +5,6 @@
|
|||||||
package components
|
package components
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/gdamore/tcell/v2"
|
|
||||||
"github.com/rivo/tview"
|
"github.com/rivo/tview"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -15,8 +14,6 @@ func NewFormLabel(label string) *FormLabel {
|
|||||||
tview.NewTextView().SetText(label),
|
tview.NewTextView().SetText(label),
|
||||||
}
|
}
|
||||||
|
|
||||||
res.SetWordWrap(true)
|
|
||||||
|
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,25 +21,3 @@ func NewFormLabel(label string) *FormLabel {
|
|||||||
type FormLabel struct {
|
type FormLabel struct {
|
||||||
*tview.TextView
|
*tview.TextView
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetLabel implements FormItem interface.
|
|
||||||
func (fl *FormLabel) GetLabel() string {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetFormAttributes implements FormItem interface.
|
|
||||||
func (fl *FormLabel) SetFormAttributes(labelWidth int, labelColor, bgColor, fieldTextColor, fieldBgColor tcell.Color) tview.FormItem {
|
|
||||||
fl.SetBackgroundColor(bgColor)
|
|
||||||
|
|
||||||
return fl
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetFieldWidth implements FormItem interface.
|
|
||||||
func (fl *FormLabel) GetFieldWidth() int {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetFinishedFunc implements FormItem interface.
|
|
||||||
func (fl *FormLabel) SetFinishedFunc(handler func(key tcell.Key)) tview.FormItem {
|
|
||||||
return fl
|
|
||||||
}
|
|
||||||
|
210
internal/pkg/tui/components/table.go
Normal file
210
internal/pkg/tui/components/table.go
Normal file
@ -0,0 +1,210 @@
|
|||||||
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
package components
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gdamore/tcell/v2"
|
||||||
|
"github.com/rivo/tview"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
backgroundColor = tcell.Color235
|
||||||
|
textNormalColor = tcell.ColorIvory
|
||||||
|
selectedTextColor = tview.Styles.PrimaryTextColor
|
||||||
|
selectedBackgroundColor = tview.Styles.ContrastBackgroundColor
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewTable creates new table.
|
||||||
|
func NewTable() *Table {
|
||||||
|
t := &Table{
|
||||||
|
Table: tview.NewTable(),
|
||||||
|
selectedRow: -1,
|
||||||
|
hoveredRow: -1,
|
||||||
|
rows: [][]interface{}{},
|
||||||
|
}
|
||||||
|
|
||||||
|
hasFocus := false
|
||||||
|
|
||||||
|
t.SetDrawFunc(func(screen tcell.Screen, x, y, width, height int) (int, int, int, int) {
|
||||||
|
changed := hasFocus != t.HasFocus()
|
||||||
|
if !changed {
|
||||||
|
return x, y, width, height
|
||||||
|
}
|
||||||
|
|
||||||
|
hasFocus = t.HasFocus()
|
||||||
|
|
||||||
|
if hasFocus {
|
||||||
|
if t.selectedRow != -1 {
|
||||||
|
t.HoverRow(t.selectedRow)
|
||||||
|
} else {
|
||||||
|
t.HoverRow(1)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
t.HoverRow(-1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return x, y, width, height
|
||||||
|
})
|
||||||
|
|
||||||
|
t.SetInputCapture(func(e *tcell.EventKey) *tcell.EventKey {
|
||||||
|
// nolint:exhaustive
|
||||||
|
switch e.Key() {
|
||||||
|
case tcell.KeyUp:
|
||||||
|
if t.hoveredRow > 0 {
|
||||||
|
t.HoverRow(t.hoveredRow - 1)
|
||||||
|
}
|
||||||
|
case tcell.KeyDown:
|
||||||
|
if t.hoveredRow < t.GetRowCount() {
|
||||||
|
t.HoverRow(t.hoveredRow + 1)
|
||||||
|
}
|
||||||
|
case tcell.KeyEnter:
|
||||||
|
if t.hoveredRow != -1 {
|
||||||
|
t.SelectRow(t.hoveredRow)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return e
|
||||||
|
})
|
||||||
|
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
// Table list of choices represented in table format.
|
||||||
|
type Table struct {
|
||||||
|
*tview.Table
|
||||||
|
selectedRow int
|
||||||
|
hoveredRow int
|
||||||
|
onRowSelected func(row int)
|
||||||
|
rows [][]interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetHeader sets table header.
|
||||||
|
func (t *Table) SetHeader(keys ...interface{}) {
|
||||||
|
t.AddRow(keys...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddRow adds a new row to the table.
|
||||||
|
func (t *Table) AddRow(columns ...interface{}) {
|
||||||
|
row := t.GetRowCount()
|
||||||
|
col := backgroundColor
|
||||||
|
textColor := tview.Styles.PrimaryTextColor
|
||||||
|
|
||||||
|
if row == 0 {
|
||||||
|
col = tcell.ColorSilver
|
||||||
|
textColor = tview.Styles.InverseTextColor
|
||||||
|
} else {
|
||||||
|
t.rows = append(t.rows, columns)
|
||||||
|
}
|
||||||
|
|
||||||
|
cell := tview.NewTableCell(" ").
|
||||||
|
SetAlign(tview.AlignCenter).
|
||||||
|
SetBackgroundColor(col).
|
||||||
|
SetTextColor(textColor)
|
||||||
|
|
||||||
|
if row > 0 {
|
||||||
|
cell.SetClickedFunc(func() bool {
|
||||||
|
t.HoverRow(row)
|
||||||
|
t.SelectRow(row)
|
||||||
|
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
t.SetCell(row, 0, cell)
|
||||||
|
|
||||||
|
for i, text := range columns {
|
||||||
|
cell = tview.NewTableCell(text.(string))
|
||||||
|
cell.SetExpansion(1)
|
||||||
|
cell.SetTextColor(textColor)
|
||||||
|
|
||||||
|
if i == len(columns)-1 {
|
||||||
|
cell.SetAlign(tview.AlignRight)
|
||||||
|
}
|
||||||
|
|
||||||
|
cell.SetBackgroundColor(col)
|
||||||
|
cell.SetSelectable(true)
|
||||||
|
t.SetCell(row, i+1, cell)
|
||||||
|
|
||||||
|
if row > 0 {
|
||||||
|
cell.SetClickedFunc(func() bool {
|
||||||
|
return t.HoverRow(row)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SelectRow selects the row in the table.
|
||||||
|
func (t *Table) SelectRow(row int) bool {
|
||||||
|
// don't select the header
|
||||||
|
if row < 2 {
|
||||||
|
row = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if row < t.GetRowCount() {
|
||||||
|
if t.selectedRow != -1 {
|
||||||
|
t.GetCell(t.selectedRow, 0).SetText(" ")
|
||||||
|
}
|
||||||
|
|
||||||
|
t.GetCell(row, 0).SetText("►")
|
||||||
|
t.selectedRow = row
|
||||||
|
|
||||||
|
if t.onRowSelected != nil {
|
||||||
|
t.onRowSelected(row)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// HoverRow highlights the row in the table.
|
||||||
|
func (t *Table) HoverRow(row int) bool {
|
||||||
|
updateRowStyle := func(r int, foregroundColor, backgroundColor tcell.Color) {
|
||||||
|
for i := 0; i < t.GetColumnCount(); i++ {
|
||||||
|
t.GetCell(r, i).SetBackgroundColor(backgroundColor).SetTextColor(foregroundColor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't select the header
|
||||||
|
if row == 0 {
|
||||||
|
row = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if row < t.GetRowCount() {
|
||||||
|
if t.hoveredRow != -1 {
|
||||||
|
updateRowStyle(t.hoveredRow, textNormalColor, backgroundColor)
|
||||||
|
}
|
||||||
|
|
||||||
|
if row != -1 {
|
||||||
|
updateRowStyle(row, selectedTextColor, selectedBackgroundColor)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.hoveredRow = row
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetHeight implements Multiline interface.
|
||||||
|
func (t *Table) GetHeight() int {
|
||||||
|
return t.GetRowCount()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetRowSelectedFunc called when selected row is updated.
|
||||||
|
func (t *Table) SetRowSelectedFunc(callback func(row int)) {
|
||||||
|
t.onRowSelected = callback
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetValue returns value in row/column.
|
||||||
|
func (t *Table) GetValue(row, column int) interface{} {
|
||||||
|
if row < len(t.rows) && column < len(t.rows[row]) {
|
||||||
|
return t.rows[row][column]
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
@ -45,6 +45,14 @@ type Item struct {
|
|||||||
options []interface{}
|
options []interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TableHeaders represents table headers list for item options which are using table representation.
|
||||||
|
type TableHeaders []interface{}
|
||||||
|
|
||||||
|
// NewTableHeaders creates TableHeaders object.
|
||||||
|
func NewTableHeaders(headers ...interface{}) TableHeaders {
|
||||||
|
return TableHeaders(headers)
|
||||||
|
}
|
||||||
|
|
||||||
// NewItem creates new form item.
|
// NewItem creates new form item.
|
||||||
func NewItem(name, description string, dest interface{}, options ...interface{}) *Item {
|
func NewItem(name, description string, dest interface{}, options ...interface{}) *Item {
|
||||||
return &Item{
|
return &Item{
|
||||||
@ -62,8 +70,8 @@ func (item *Item) assign(value string) error {
|
|||||||
|
|
||||||
// createFormItems dynamically creates tview.FormItem list based on the wrapped type.
|
// createFormItems dynamically creates tview.FormItem list based on the wrapped type.
|
||||||
// nolint:gocyclo
|
// nolint:gocyclo
|
||||||
func (item *Item) createFormItems() ([]tview.FormItem, error) {
|
func (item *Item) createFormItems() ([]tview.Primitive, error) {
|
||||||
res := []tview.FormItem{}
|
res := []tview.Primitive{}
|
||||||
|
|
||||||
v := reflect.ValueOf(item.dest)
|
v := reflect.ValueOf(item.dest)
|
||||||
if v.Kind() == reflect.Ptr {
|
if v.Kind() == reflect.Ptr {
|
||||||
@ -77,7 +85,7 @@ func (item *Item) createFormItems() ([]tview.FormItem, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var formItem tview.FormItem
|
var formItem tview.Primitive
|
||||||
|
|
||||||
// nolint:exhaustive
|
// nolint:exhaustive
|
||||||
switch v.Kind() {
|
switch v.Kind() {
|
||||||
@ -92,37 +100,69 @@ func (item *Item) createFormItems() ([]tview.FormItem, error) {
|
|||||||
formItem = checkbox
|
formItem = checkbox
|
||||||
default:
|
default:
|
||||||
if len(item.options) > 0 {
|
if len(item.options) > 0 {
|
||||||
dropdown := tview.NewDropDown()
|
tableHeaders, ok := item.options[0].(TableHeaders)
|
||||||
|
if ok {
|
||||||
|
table := components.NewTable()
|
||||||
|
table.SetHeader(tableHeaders...)
|
||||||
|
|
||||||
if len(item.options)%2 != 0 {
|
data := item.options[1:]
|
||||||
return nil, fmt.Errorf("wrong amount of arguments for options: should be even amount of key, value pairs")
|
numColumns := len(tableHeaders)
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < len(item.options); i += 2 {
|
if len(data)%numColumns != 0 {
|
||||||
if optionName, ok := item.options[i].(string); ok {
|
return nil, fmt.Errorf("incorrect amount of data provided for the table")
|
||||||
selected := -1
|
|
||||||
|
|
||||||
func(index int) {
|
|
||||||
dropdown.AddOption(optionName, func() {
|
|
||||||
v.Set(reflect.ValueOf(item.options[index]))
|
|
||||||
})
|
|
||||||
|
|
||||||
if v.Interface() == item.options[index] {
|
|
||||||
selected = i / 2
|
|
||||||
}
|
|
||||||
}(i + 1)
|
|
||||||
|
|
||||||
if selected != -1 {
|
|
||||||
dropdown.SetCurrentOption(selected)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return nil, fmt.Errorf("expected string option name, got %s", item.options[i])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
selected := -1
|
||||||
|
|
||||||
|
for i := 0; i < len(data); i += numColumns {
|
||||||
|
table.AddRow(data[i : i+numColumns]...)
|
||||||
|
|
||||||
|
if v.Interface() == data[i] {
|
||||||
|
selected = i / numColumns
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if selected != -1 {
|
||||||
|
table.SelectRow(selected)
|
||||||
|
}
|
||||||
|
|
||||||
|
formItem = table
|
||||||
|
table.SetRowSelectedFunc(func(row int) {
|
||||||
|
v.Set(reflect.ValueOf(table.GetValue(row, 0))) // always pick the first column
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
dropdown := tview.NewDropDown()
|
||||||
|
|
||||||
|
if len(item.options)%2 != 0 {
|
||||||
|
return nil, fmt.Errorf("wrong amount of arguments for options: should be even amount of key, value pairs")
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < len(item.options); i += 2 {
|
||||||
|
if optionName, ok := item.options[i].(string); ok {
|
||||||
|
selected := -1
|
||||||
|
|
||||||
|
func(index int) {
|
||||||
|
dropdown.AddOption(optionName, func() {
|
||||||
|
v.Set(reflect.ValueOf(item.options[index]))
|
||||||
|
})
|
||||||
|
|
||||||
|
if v.Interface() == item.options[index] {
|
||||||
|
selected = i / 2
|
||||||
|
}
|
||||||
|
}(i + 1)
|
||||||
|
|
||||||
|
if selected != -1 {
|
||||||
|
dropdown.SetCurrentOption(selected)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return nil, fmt.Errorf("expected string option name, got %s", item.options[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dropdown.SetLabel(item.name)
|
||||||
|
|
||||||
|
formItem = dropdown
|
||||||
}
|
}
|
||||||
|
|
||||||
dropdown.SetLabel(item.name)
|
|
||||||
|
|
||||||
formItem = dropdown
|
|
||||||
} else {
|
} else {
|
||||||
input := tview.NewInputField()
|
input := tview.NewInputField()
|
||||||
formItem = input
|
formItem = input
|
||||||
@ -375,7 +415,8 @@ func (installer *Installer) configure() error {
|
|||||||
groups = append(groups, eg)
|
groups = append(groups, eg)
|
||||||
|
|
||||||
err = func(index int) error {
|
err = func(index int) error {
|
||||||
form := tview.NewForm()
|
form := components.NewForm()
|
||||||
|
form.SetBackgroundColor(color)
|
||||||
|
|
||||||
for _, item := range p.items {
|
for _, item := range p.items {
|
||||||
formItems, e := item.createFormItems()
|
formItems, e := item.createFormItems()
|
||||||
|
@ -46,7 +46,9 @@ func NewState(ctx context.Context, conn *Connection) (*State, error) {
|
|||||||
opts.ClusterConfig.ControlPlane.Endpoint = fmt.Sprintf("https://%s:%d", conn.nodeEndpoint, constants.DefaultControlPlanePort)
|
opts.ClusterConfig.ControlPlane.Endpoint = fmt.Sprintf("https://%s:%d", conn.nodeEndpoint, constants.DefaultControlPlanePort)
|
||||||
}
|
}
|
||||||
|
|
||||||
diskInstallOptions := []interface{}{}
|
diskInstallOptions := []interface{}{
|
||||||
|
NewTableHeaders("device name", "model name", "size"),
|
||||||
|
}
|
||||||
|
|
||||||
disks, err := conn.Disks()
|
disks, err := conn.Disks()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -58,8 +60,7 @@ func NewState(ctx context.Context, conn *Connection) (*State, error) {
|
|||||||
opts.MachineConfig.InstallConfig.InstallDisk = disk.DeviceName
|
opts.MachineConfig.InstallConfig.InstallDisk = disk.DeviceName
|
||||||
}
|
}
|
||||||
|
|
||||||
name := fmt.Sprintf("%s %s %s", disk.DeviceName, disk.Model, humanize.Bytes(disk.Size))
|
diskInstallOptions = append(diskInstallOptions, disk.DeviceName, disk.Model, humanize.Bytes(disk.Size))
|
||||||
diskInstallOptions = append(diskInstallOptions, name, disk.DeviceName)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var machineTypes []interface{}
|
var machineTypes []interface{}
|
||||||
@ -80,7 +81,26 @@ func NewState(ctx context.Context, conn *Connection) (*State, error) {
|
|||||||
conn: conn,
|
conn: conn,
|
||||||
opts: opts,
|
opts: opts,
|
||||||
pages: []*Page{
|
pages: []*Page{
|
||||||
|
NewPage("Installer Params",
|
||||||
|
NewItem(
|
||||||
|
"image",
|
||||||
|
v1alpha1.InstallConfigDoc.Describe("image", true),
|
||||||
|
&opts.MachineConfig.InstallConfig.InstallImage,
|
||||||
|
),
|
||||||
|
NewItem(
|
||||||
|
"install disk",
|
||||||
|
v1alpha1.InstallConfigDoc.Describe("disk", true),
|
||||||
|
&opts.MachineConfig.InstallConfig.InstallDisk,
|
||||||
|
diskInstallOptions...,
|
||||||
|
),
|
||||||
|
),
|
||||||
NewPage("Machine Config",
|
NewPage("Machine Config",
|
||||||
|
NewItem(
|
||||||
|
"machine type",
|
||||||
|
v1alpha1.MachineConfigDoc.Describe("type", true),
|
||||||
|
&opts.MachineConfig.Type,
|
||||||
|
machineTypes...,
|
||||||
|
),
|
||||||
NewItem(
|
NewItem(
|
||||||
"cluster name",
|
"cluster name",
|
||||||
v1alpha1.ClusterConfigDoc.Describe("clusterName", true),
|
v1alpha1.ClusterConfigDoc.Describe("clusterName", true),
|
||||||
@ -91,28 +111,11 @@ func NewState(ctx context.Context, conn *Connection) (*State, error) {
|
|||||||
v1alpha1.ControlPlaneConfigDoc.Describe("endpoint", true),
|
v1alpha1.ControlPlaneConfigDoc.Describe("endpoint", true),
|
||||||
&opts.ClusterConfig.ControlPlane.Endpoint,
|
&opts.ClusterConfig.ControlPlane.Endpoint,
|
||||||
),
|
),
|
||||||
NewItem(
|
|
||||||
"machine type",
|
|
||||||
v1alpha1.MachineConfigDoc.Describe("type", true),
|
|
||||||
&opts.MachineConfig.Type,
|
|
||||||
machineTypes...,
|
|
||||||
),
|
|
||||||
NewItem(
|
NewItem(
|
||||||
"kubernetes version",
|
"kubernetes version",
|
||||||
"Kubernetes version to install.",
|
"Kubernetes version to install.",
|
||||||
&opts.MachineConfig.KubernetesVersion,
|
&opts.MachineConfig.KubernetesVersion,
|
||||||
),
|
),
|
||||||
NewItem(
|
|
||||||
"install disk",
|
|
||||||
v1alpha1.InstallConfigDoc.Describe("disk", true),
|
|
||||||
&opts.MachineConfig.InstallConfig.InstallDisk,
|
|
||||||
diskInstallOptions...,
|
|
||||||
),
|
|
||||||
NewItem(
|
|
||||||
"image",
|
|
||||||
v1alpha1.InstallConfigDoc.Describe("image", true),
|
|
||||||
&opts.MachineConfig.InstallConfig.InstallImage,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
NewPage("Network Config",
|
NewPage("Network Config",
|
||||||
NewItem(
|
NewItem(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user