Class: Pvectl::Config::Wizard

Inherits:
Object
  • Object
show all
Defined in:
lib/pvectl/config/wizard.rb,
sig/pvectl/config/wizard.rbs

Overview

Interactive configuration wizard for first-time setup.

Wizard guides users through initial configuration by prompting for server URL, authentication credentials, and SSL settings. It only runs when stdin is a TTY (not in pipes or scripts).

Examples:

Checking if wizard is available

if Wizard.available?
  wizard = Wizard.new
  config = wizard.run
end

Using custom prompt (for testing)

wizard = Wizard.new(prompt: mock_prompt)
config = wizard.run

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(prompt: nil) ⇒ Wizard

Creates a new Wizard instance.



32
33
34
# File 'lib/pvectl/config/wizard.rb', line 32

def initialize(prompt: nil)
  @prompt = prompt || create_default_prompt
end

Instance Attribute Details

#promptObject (readonly)

Returns the value of attribute prompt.



57
58
59
# File 'lib/pvectl/config/wizard.rb', line 57

def prompt
  @prompt
end

Class Method Details

.available?Boolean

Checks if the wizard can run (stdin is a TTY).



25
26
27
# File 'lib/pvectl/config/wizard.rb', line 25

def self.available?
  $stdin.tty?
end

Instance Method Details

#build_config(server:, verify_ssl:, auth_type:, credentials:, context_name:) ⇒ Hash

Builds the configuration hash from collected data.



130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/pvectl/config/wizard.rb', line 130

def build_config(server:, verify_ssl:, auth_type:, credentials:, context_name:)
  cluster_name = context_name
  user_name = "#{context_name}-user"

  {
    "apiVersion" => "pvectl/v1",
    "kind" => "Config",
    "clusters" => [
      {
        "name" => cluster_name,
        "cluster" => {
          "server" => server,
          "insecure-skip-tls-verify" => !verify_ssl
        }
      }
    ],
    "users" => [
      build_user_config(user_name, auth_type, credentials)
    ],
    "contexts" => [
      {
        "name" => context_name,
        "context" => {
          "cluster" => cluster_name,
          "user" => user_name
        }
      }
    ],
    "current-context" => context_name
  }
end

#build_user_config(name, auth_type, credentials) ⇒ Hash

Builds user configuration hash.



168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/pvectl/config/wizard.rb', line 168

def build_user_config(name, auth_type, credentials)
  user_data = if auth_type == :token
                {
                  "token-id" => credentials[:token_id],
                  "token-secret" => credentials[:token_secret]
                }
              else
                {
                  "username" => credentials[:username],
                  "password" => credentials[:password]
                }
              end

  {
    "name" => name,
    "user" => user_data
  }
end

#create_default_promptObject

Creates a default prompt using TTY::Prompt if available.



62
63
64
65
66
67
68
69
70
71
# File 'lib/pvectl/config/wizard.rb', line 62

def create_default_prompt
  # Try to load TTY::Prompt if available
  begin
    require "tty-prompt"
    TTY::Prompt.new
  rescue LoadError
    # Fallback to simple prompt
    SimplePrompt.new
  end
end

#prompt_auth_typeSymbol

Prompts for authentication type selection.



90
91
92
93
94
95
# File 'lib/pvectl/config/wizard.rb', line 90

def prompt_auth_type
  prompt.select("Authentication method:", [
    { name: "API Token (recommended)", value: :token },
    { name: "Username/Password", value: :password }
  ])
end

#prompt_context_nameString

Prompts for context name.



118
119
120
# File 'lib/pvectl/config/wizard.rb', line 118

def prompt_context_name
  prompt.ask("Context name:", default: "default")
end

#prompt_credentials(auth_type) ⇒ Hash

Prompts for authentication credentials.



101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/pvectl/config/wizard.rb', line 101

def prompt_credentials(auth_type)
  if auth_type == :token
    {
      token_id: prompt.ask("Token ID (e.g., root@pam!tokenid):"),
      token_secret: prompt.mask("Token Secret:")
    }
  else
    {
      username: prompt.ask("Username (e.g., root@pam):"),
      password: prompt.mask("Password:")
    }
  end
end

#prompt_serverString

Prompts for the Proxmox server URL.



76
77
78
# File 'lib/pvectl/config/wizard.rb', line 76

def prompt_server
  prompt.ask("Proxmox server URL (e.g., https://pve.example.com:8006):")
end

#prompt_sslBoolean

Prompts for SSL verification preference.



83
84
85
# File 'lib/pvectl/config/wizard.rb', line 83

def prompt_ssl
  prompt.yes?("Verify SSL certificate?")
end

#runHash

Runs the interactive wizard and returns configuration.



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/pvectl/config/wizard.rb', line 39

def run
  server = prompt_server
  verify_ssl = prompt_ssl
  auth_type = prompt_auth_type
  credentials = prompt_credentials(auth_type)
  context_name = prompt_context_name

  build_config(
    server: server,
    verify_ssl: verify_ssl,
    auth_type: auth_type,
    credentials: credentials,
    context_name: context_name
  )
end

#valid_server_url?(url) ⇒ Boolean

Validates server URL format.



191
192
193
194
195
196
197
198
# File 'lib/pvectl/config/wizard.rb', line 191

def valid_server_url?(url)
  return false if url.nil? || url.empty?

  uri = URI.parse(url)
  uri.scheme == "https" && !uri.host.nil?
rescue URI::InvalidURIError
  false
end

#valid_token_id?(token_id) ⇒ Boolean

Validates token ID format.



204
205
206
207
208
# File 'lib/pvectl/config/wizard.rb', line 204

def valid_token_id?(token_id)
  return false if token_id.nil? || token_id.empty?

  token_id.include?("@") && token_id.include?("!")
end