Merge "Integrating the isogen & doc pull CTL components"
This commit is contained in:
commit
75492296df
1
go.sum
1
go.sum
@ -1019,6 +1019,7 @@ opendev.org/airship/airshipctl v0.0.0-20200501183051-71b06db81924/go.mod h1:ste8
|
|||||||
opendev.org/airship/airshipctl v0.0.0-20200518155418-7276dd68d8d0 h1:gMM7Jcb0r9bEa4kYBm9mhDNIjdtLKy3WuA4z/PabpLY=
|
opendev.org/airship/airshipctl v0.0.0-20200518155418-7276dd68d8d0 h1:gMM7Jcb0r9bEa4kYBm9mhDNIjdtLKy3WuA4z/PabpLY=
|
||||||
opendev.org/airship/airshipctl v0.0.0-20200518155418-7276dd68d8d0/go.mod h1:0ywoz1IC0yXQ0XDfcBV/BVeEubkTPPjN7dra8sUrsHs=
|
opendev.org/airship/airshipctl v0.0.0-20200518155418-7276dd68d8d0/go.mod h1:0ywoz1IC0yXQ0XDfcBV/BVeEubkTPPjN7dra8sUrsHs=
|
||||||
opendev.org/airship/airshipctl v0.0.0-20200519134509-98f14aaa9327 h1:wPnsodiekVe1lq/oxbHmk8ZCcJa1xuzPEY+yJG1lMuI=
|
opendev.org/airship/airshipctl v0.0.0-20200519134509-98f14aaa9327 h1:wPnsodiekVe1lq/oxbHmk8ZCcJa1xuzPEY+yJG1lMuI=
|
||||||
|
opendev.org/airship/airshipctl v0.0.0-20200608220007-d31f4f982869 h1:JVshDs4fIvy0Fr8aN3H1xwP9NHedLBEjY+pT9AlHGbw=
|
||||||
opendev.org/airship/go-redfish v0.0.0-20200110185254-3ab47e28bae8/go.mod h1:FEjYcb3bYBWGpQIqtvVM0NrT5eyjlCOCj5JNf4lI+6s=
|
opendev.org/airship/go-redfish v0.0.0-20200110185254-3ab47e28bae8/go.mod h1:FEjYcb3bYBWGpQIqtvVM0NrT5eyjlCOCj5JNf4lI+6s=
|
||||||
opendev.org/airship/go-redfish v0.0.0-20200318103738-db034d1d753a h1:4ggAMTwpfu/w3ZXOIJ9tfYF37JIYn+eNCA4O10NduZ0=
|
opendev.org/airship/go-redfish v0.0.0-20200318103738-db034d1d753a h1:4ggAMTwpfu/w3ZXOIJ9tfYF37JIYn+eNCA4O10NduZ0=
|
||||||
opendev.org/airship/go-redfish v0.0.0-20200318103738-db034d1d753a/go.mod h1:FEjYcb3bYBWGpQIqtvVM0NrT5eyjlCOCj5JNf4lI+6s=
|
opendev.org/airship/go-redfish v0.0.0-20200318103738-db034d1d753a/go.mod h1:FEjYcb3bYBWGpQIqtvVM0NrT5eyjlCOCj5JNf4lI+6s=
|
||||||
|
@ -99,10 +99,16 @@ const (
|
|||||||
SetConfig WsComponentType = "setConfig"
|
SetConfig WsComponentType = "setConfig"
|
||||||
Initialize WsComponentType = "initialize"
|
Initialize WsComponentType = "initialize"
|
||||||
Keepalive WsComponentType = "keepalive"
|
Keepalive WsComponentType = "keepalive"
|
||||||
|
CTLConfig WsComponentType = "config"
|
||||||
|
Baremetal WsComponentType = "baremetal"
|
||||||
|
Document WsComponentType = "document"
|
||||||
|
|
||||||
|
GetDefaults WsSubComponentType = "getDefaults"
|
||||||
SetContext WsSubComponentType = "context"
|
SetContext WsSubComponentType = "context"
|
||||||
SetCluster WsSubComponentType = "cluster"
|
SetCluster WsSubComponentType = "cluster"
|
||||||
SetCredential WsSubComponentType = "credential"
|
SetCredential WsSubComponentType = "credential"
|
||||||
|
GenerateISO WsSubComponentType = "generateISO"
|
||||||
|
DocPull WsSubComponentType = "docPull"
|
||||||
)
|
)
|
||||||
|
|
||||||
// WsMessage is a request / return structure used for websockets
|
// WsMessage is a request / return structure used for websockets
|
||||||
|
@ -14,13 +14,22 @@
|
|||||||
package ctl
|
package ctl
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
"bytes"
|
||||||
|
"text/template"
|
||||||
|
|
||||||
"opendev.org/airship/airshipctl/pkg/environment"
|
"opendev.org/airship/airshipctl/pkg/environment"
|
||||||
"opendev.org/airship/airshipctl/pkg/version"
|
"opendev.org/airship/airshipctl/pkg/version"
|
||||||
"opendev.org/airship/airshipui/internal/configs"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ctlPage struct is used for templated HTML
|
||||||
|
type ctlPage struct {
|
||||||
|
ClusterRows string
|
||||||
|
ContextRows string
|
||||||
|
CredentialRows string
|
||||||
|
Title string
|
||||||
|
Version string
|
||||||
|
}
|
||||||
|
|
||||||
// client provides a library of functions that enable external programs (e.g. Airship UI) to perform airshipctl
|
// client provides a library of functions that enable external programs (e.g. Airship UI) to perform airshipctl
|
||||||
// functionality in exactly the same manner as the CLI.
|
// functionality in exactly the same manner as the CLI.
|
||||||
type client struct {
|
type client struct {
|
||||||
@ -43,21 +52,26 @@ func NewClient() *client {
|
|||||||
var c *client = NewClient()
|
var c *client = NewClient()
|
||||||
|
|
||||||
// GetAirshipCTLVersion will kick out what version of airshipctl we're using
|
// GetAirshipCTLVersion will kick out what version of airshipctl we're using
|
||||||
func GetAirshipCTLVersion() string {
|
func getAirshipCTLVersion() string {
|
||||||
return version.Get().GitVersion
|
return version.Get().GitVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetDefaults will send to the UI the basics of what airshipctl we know about
|
func getHTML(templateFile string, contents ctlPage) (string, error) {
|
||||||
func GetDefaults(configs.WsMessage) configs.WsMessage {
|
// go templates need an io writer, since we need a string this buffer can be converted
|
||||||
config, err := getDefaultHTML()
|
var buff bytes.Buffer
|
||||||
|
|
||||||
|
// TODO: make the node path dynamic or setable at compile time
|
||||||
|
t, err := template.ParseFiles(templateFile)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
config = "Error attempting to get data for AirshipCTL configs: " + err.Error()
|
return "", err
|
||||||
log.Println(err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return configs.WsMessage{
|
// parse and merge the template
|
||||||
Type: configs.AirshipCTL,
|
err = template.Must(t, err).Execute(&buff, contents)
|
||||||
Component: configs.Info,
|
if err != nil {
|
||||||
HTML: config,
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return buff.String(), nil
|
||||||
}
|
}
|
||||||
|
68
internal/integrations/ctl/baremetal.go
Executable file
68
internal/integrations/ctl/baremetal.go
Executable file
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
package ctl
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"opendev.org/airship/airshipctl/pkg/bootstrap/isogen"
|
||||||
|
"opendev.org/airship/airshipui/internal/configs"
|
||||||
|
)
|
||||||
|
|
||||||
|
// HandleBaremetalRequest will flop between requests so we don't have to have them all mapped as function calls
|
||||||
|
func HandleBaremetalRequest(request configs.WsMessage) configs.WsMessage {
|
||||||
|
response := configs.WsMessage{
|
||||||
|
Type: configs.AirshipCTL,
|
||||||
|
Component: configs.Baremetal,
|
||||||
|
SubComponent: request.SubComponent,
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
var message string
|
||||||
|
switch request.SubComponent {
|
||||||
|
case configs.GetDefaults:
|
||||||
|
response.HTML, err = getBaremetalHTML()
|
||||||
|
case configs.DocPull:
|
||||||
|
message, err = c.docPull()
|
||||||
|
case configs.GenerateISO:
|
||||||
|
message, err = c.generateIso()
|
||||||
|
default:
|
||||||
|
err = fmt.Errorf("Subcomponent %s not found", request.SubComponent)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
response.Error = err.Error()
|
||||||
|
} else {
|
||||||
|
response.Message = message
|
||||||
|
}
|
||||||
|
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *client) generateIso() (string, error) {
|
||||||
|
var message string
|
||||||
|
err := isogen.GenerateBootstrapIso(c.settings)
|
||||||
|
if err == nil {
|
||||||
|
message = fmt.Sprintf("Success")
|
||||||
|
}
|
||||||
|
|
||||||
|
return message, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func getBaremetalHTML() (string, error) {
|
||||||
|
return getHTML("./internal/integrations/ctl/templates/baremetal.html", ctlPage{
|
||||||
|
Title: "Baremetal",
|
||||||
|
Version: getAirshipCTLVersion(),
|
||||||
|
})
|
||||||
|
}
|
@ -14,134 +14,25 @@
|
|||||||
package ctl
|
package ctl
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"text/template"
|
|
||||||
|
|
||||||
"opendev.org/airship/airshipctl/pkg/config"
|
"opendev.org/airship/airshipctl/pkg/config"
|
||||||
"opendev.org/airship/airshipui/internal/configs"
|
"opendev.org/airship/airshipui/internal/configs"
|
||||||
)
|
)
|
||||||
|
|
||||||
// configPage struct is used for templated HTML
|
// HandleConfigRequest will flop between requests so we don't have to have them all mapped as function calls
|
||||||
type configPage struct {
|
func HandleConfigRequest(request configs.WsMessage) configs.WsMessage {
|
||||||
ClusterRows string
|
|
||||||
ContextRows string
|
|
||||||
CredentialRows string
|
|
||||||
Title string
|
|
||||||
Version string
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetCluster gets cluster information from the airshipctl config
|
|
||||||
func (c *client) GetCluster() []*config.Cluster {
|
|
||||||
return c.settings.Config.GetClusters()
|
|
||||||
}
|
|
||||||
|
|
||||||
// getClusterTableRows turns an array of cluster into html table rows
|
|
||||||
func getClusterTableRows() string {
|
|
||||||
info := c.GetCluster()
|
|
||||||
|
|
||||||
var rows string
|
|
||||||
for _, config := range info {
|
|
||||||
// TODO: all rows are editable, probably shouldn't be
|
|
||||||
rows += "<tr><td><div contenteditable=true>" +
|
|
||||||
config.Bootstrap + "</div></td><td><div contenteditable=true>" +
|
|
||||||
config.NameInKubeconf + "</div></td><td><div contenteditable=true>" +
|
|
||||||
config.ManagementConfiguration + "</div></td><td>" +
|
|
||||||
config.KubeCluster().LocationOfOrigin + "</td><td><div contenteditable=true>" +
|
|
||||||
config.KubeCluster().Server + "</div></td><td><div contenteditable=true>" +
|
|
||||||
config.KubeCluster().CertificateAuthority + "</div></td><td>" +
|
|
||||||
"<button type=\"button\" class=\"btn btn-success\" onclick=\"saveConfig(this)\">Save</button></td></tr>"
|
|
||||||
}
|
|
||||||
return rows
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetContext gets cluster information from the airshipctl config
|
|
||||||
func (c *client) GetContext() []*config.Context {
|
|
||||||
return c.settings.Config.GetContexts()
|
|
||||||
}
|
|
||||||
|
|
||||||
// getContextTableRows turns an array of contexts into html table rows
|
|
||||||
func getContextTableRows() string {
|
|
||||||
info := c.GetContext()
|
|
||||||
|
|
||||||
var rows string
|
|
||||||
for _, context := range info {
|
|
||||||
// TODO: all rows are editable, probably shouldn't be
|
|
||||||
rows += "<tr><td><div contenteditable=true>" +
|
|
||||||
context.NameInKubeconf + "</div></td><td><div contenteditable=true>" +
|
|
||||||
context.Manifest + "</div></td><td>" +
|
|
||||||
context.KubeContext().LocationOfOrigin + "</td><td><div contenteditable=true>" +
|
|
||||||
context.KubeContext().Cluster + "</div></td><td><div contenteditable=true>" +
|
|
||||||
context.KubeContext().AuthInfo + "</div></td><td>" +
|
|
||||||
"<button type=\"button\" class=\"btn btn-success\" onclick=\"saveConfig(this)\">Save</button></td></tr>"
|
|
||||||
}
|
|
||||||
return rows
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetCredential gets user credentials from the airshipctl config
|
|
||||||
func (c *client) GetCredential() []*config.AuthInfo {
|
|
||||||
authinfo, err := c.settings.Config.GetAuthInfos()
|
|
||||||
if err != nil {
|
|
||||||
return []*config.AuthInfo{}
|
|
||||||
}
|
|
||||||
|
|
||||||
return authinfo
|
|
||||||
}
|
|
||||||
|
|
||||||
// getContextTableRows turns an array of contexts into html table rows
|
|
||||||
func getCredentialTableRows() string {
|
|
||||||
info := c.GetCredential()
|
|
||||||
|
|
||||||
var rows string
|
|
||||||
for _, credential := range info {
|
|
||||||
// TODO: all rows are editable, probably shouldn't be
|
|
||||||
rows += "<tr><td>" +
|
|
||||||
credential.KubeAuthInfo().LocationOfOrigin + "</td><td><div contenteditable=true>" +
|
|
||||||
credential.KubeAuthInfo().Username + "</div></td><td>" +
|
|
||||||
"<button type=\"button\" class=\"btn btn-success\" onclick=\"saveConfig(this)\">Save</button></td></tr>"
|
|
||||||
}
|
|
||||||
return rows
|
|
||||||
}
|
|
||||||
|
|
||||||
func getDefaultHTML() (string, error) {
|
|
||||||
// go templates need an io writer, since we need a string this buffer can be converted
|
|
||||||
var buff bytes.Buffer
|
|
||||||
|
|
||||||
// TODO: make the node path dynamic or setable at compile time
|
|
||||||
t, err := template.ParseFiles("./internal/integrations/ctl/templates/config.html")
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
// add contents to the page
|
|
||||||
p := configPage{
|
|
||||||
ClusterRows: getClusterTableRows(),
|
|
||||||
ContextRows: getContextTableRows(),
|
|
||||||
CredentialRows: getCredentialTableRows(),
|
|
||||||
Title: "Config",
|
|
||||||
Version: GetAirshipCTLVersion(),
|
|
||||||
}
|
|
||||||
|
|
||||||
// parse and merge the template
|
|
||||||
err = template.Must(t, err).Execute(&buff, p)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return buff.String(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetConfig will flop between requests so we don't have to have them all mapped as function calls
|
|
||||||
func SetConfig(request configs.WsMessage) configs.WsMessage {
|
|
||||||
response := configs.WsMessage{
|
response := configs.WsMessage{
|
||||||
Type: configs.AirshipCTL,
|
Type: configs.AirshipCTL,
|
||||||
Component: configs.SetConfig,
|
Component: configs.CTLConfig,
|
||||||
|
SubComponent: request.SubComponent,
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
var message string
|
var message string
|
||||||
switch request.SubComponent {
|
switch request.SubComponent {
|
||||||
|
case configs.GetDefaults:
|
||||||
|
response.HTML, err = getConfigHTML()
|
||||||
case configs.SetContext:
|
case configs.SetContext:
|
||||||
message, err = setContext(request)
|
message, err = setContext(request)
|
||||||
case configs.SetCluster:
|
case configs.SetCluster:
|
||||||
@ -161,6 +52,88 @@ func SetConfig(request configs.WsMessage) configs.WsMessage {
|
|||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetCluster gets cluster information from the airshipctl config
|
||||||
|
func (c *client) getCluster() []*config.Cluster {
|
||||||
|
return c.settings.Config.GetClusters()
|
||||||
|
}
|
||||||
|
|
||||||
|
// getClusterTableRows turns an array of cluster into html table rows
|
||||||
|
func getClusterTableRows() string {
|
||||||
|
info := c.getCluster()
|
||||||
|
|
||||||
|
var rows string
|
||||||
|
for _, config := range info {
|
||||||
|
// TODO: all rows are editable, probably shouldn't be
|
||||||
|
rows += "<tr><td><div contenteditable=true>" +
|
||||||
|
config.Bootstrap + "</div></td><td><div contenteditable=true>" +
|
||||||
|
config.NameInKubeconf + "</div></td><td><div contenteditable=true>" +
|
||||||
|
config.ManagementConfiguration + "</div></td><td>" +
|
||||||
|
config.KubeCluster().LocationOfOrigin + "</td><td><div contenteditable=true>" +
|
||||||
|
config.KubeCluster().Server + "</div></td><td><div contenteditable=true>" +
|
||||||
|
config.KubeCluster().CertificateAuthority + "</div></td><td>" +
|
||||||
|
"<button type=\"button\" class=\"btn btn-success\" onclick=\"saveConfig(this)\">Save</button></td></tr>"
|
||||||
|
}
|
||||||
|
return rows
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetContext gets cluster information from the airshipctl config
|
||||||
|
func (c *client) getContext() []*config.Context {
|
||||||
|
return c.settings.Config.GetContexts()
|
||||||
|
}
|
||||||
|
|
||||||
|
// getContextTableRows turns an array of contexts into html table rows
|
||||||
|
func getContextTableRows() string {
|
||||||
|
info := c.getContext()
|
||||||
|
|
||||||
|
var rows string
|
||||||
|
for _, context := range info {
|
||||||
|
// TODO: all rows are editable, probably shouldn't be
|
||||||
|
rows += "<tr><td><div contenteditable=true>" +
|
||||||
|
context.NameInKubeconf + "</div></td><td><div contenteditable=true>" +
|
||||||
|
context.Manifest + "</div></td><td>" +
|
||||||
|
context.KubeContext().LocationOfOrigin + "</td><td><div contenteditable=true>" +
|
||||||
|
context.KubeContext().Cluster + "</div></td><td><div contenteditable=true>" +
|
||||||
|
context.KubeContext().AuthInfo + "</div></td><td>" +
|
||||||
|
"<button type=\"button\" class=\"btn btn-success\" onclick=\"saveConfig(this)\">Save</button></td></tr>"
|
||||||
|
}
|
||||||
|
return rows
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCredential gets user credentials from the airshipctl config
|
||||||
|
func (c *client) getCredential() []*config.AuthInfo {
|
||||||
|
authinfo, err := c.settings.Config.GetAuthInfos()
|
||||||
|
if err != nil {
|
||||||
|
return []*config.AuthInfo{}
|
||||||
|
}
|
||||||
|
|
||||||
|
return authinfo
|
||||||
|
}
|
||||||
|
|
||||||
|
// getContextTableRows turns an array of contexts into html table rows
|
||||||
|
func getCredentialTableRows() string {
|
||||||
|
info := c.getCredential()
|
||||||
|
|
||||||
|
var rows string
|
||||||
|
for _, credential := range info {
|
||||||
|
// TODO: all rows are editable, probably shouldn't be
|
||||||
|
rows += "<tr><td>" +
|
||||||
|
credential.KubeAuthInfo().LocationOfOrigin + "</td><td><div contenteditable=true>" +
|
||||||
|
credential.KubeAuthInfo().Username + "</div></td><td>" +
|
||||||
|
"<button type=\"button\" class=\"btn btn-success\" onclick=\"saveConfig(this)\">Save</button></td></tr>"
|
||||||
|
}
|
||||||
|
return rows
|
||||||
|
}
|
||||||
|
|
||||||
|
func getConfigHTML() (string, error) {
|
||||||
|
return getHTML("./internal/integrations/ctl/templates/config.html", ctlPage{
|
||||||
|
ClusterRows: getClusterTableRows(),
|
||||||
|
ContextRows: getContextTableRows(),
|
||||||
|
CredentialRows: getCredentialTableRows(),
|
||||||
|
Title: "Config",
|
||||||
|
Version: getAirshipCTLVersion(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// SetCluster will take ui cluster info, translate them into CTL commands and send a response back to the UI
|
// SetCluster will take ui cluster info, translate them into CTL commands and send a response back to the UI
|
||||||
func setCluster(request configs.WsMessage) (string, error) {
|
func setCluster(request configs.WsMessage) (string, error) {
|
||||||
modified, err := config.RunSetCluster(&request.ClusterOptions, c.settings.Config, true)
|
modified, err := config.RunSetCluster(&request.ClusterOptions, c.settings.Config, true)
|
||||||
|
67
internal/integrations/ctl/document.go
Executable file
67
internal/integrations/ctl/document.go
Executable file
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
package ctl
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"opendev.org/airship/airshipctl/pkg/document/pull"
|
||||||
|
"opendev.org/airship/airshipui/internal/configs"
|
||||||
|
)
|
||||||
|
|
||||||
|
// HandleBaremetalRequest will flop between requests so we don't have to have them all mapped as function calls
|
||||||
|
func HandleDocumentRequest(request configs.WsMessage) configs.WsMessage {
|
||||||
|
response := configs.WsMessage{
|
||||||
|
Type: configs.AirshipCTL,
|
||||||
|
Component: configs.Document,
|
||||||
|
SubComponent: request.SubComponent,
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
var message string
|
||||||
|
switch request.SubComponent {
|
||||||
|
case configs.GetDefaults:
|
||||||
|
response.HTML, err = getDocumentHTML()
|
||||||
|
case configs.DocPull:
|
||||||
|
message, err = c.docPull()
|
||||||
|
default:
|
||||||
|
err = fmt.Errorf("Subcomponent %s not found", request.SubComponent)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
response.Error = err.Error()
|
||||||
|
} else {
|
||||||
|
response.Message = message
|
||||||
|
}
|
||||||
|
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *client) docPull() (string, error) {
|
||||||
|
var message string
|
||||||
|
settings := pull.Settings{AirshipCTLSettings: c.settings}
|
||||||
|
err := settings.Pull()
|
||||||
|
if err == nil {
|
||||||
|
message = fmt.Sprintf("Success")
|
||||||
|
}
|
||||||
|
|
||||||
|
return message, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func getDocumentHTML() (string, error) {
|
||||||
|
return getHTML("./internal/integrations/ctl/templates/document.html", ctlPage{
|
||||||
|
Title: "Document",
|
||||||
|
Version: getAirshipCTLVersion(),
|
||||||
|
})
|
||||||
|
}
|
5
internal/integrations/ctl/templates/baremetal.html
Executable file
5
internal/integrations/ctl/templates/baremetal.html
Executable file
@ -0,0 +1,5 @@
|
|||||||
|
<h1>Airship CTL {{.Title}} Base Information</h1>
|
||||||
|
<p>Version: {{.Version}}</p>
|
||||||
|
|
||||||
|
<h2>Generate ISO</h2>
|
||||||
|
<button type="button" class="btn btn-info" id="GenIsoBtn" onclick="baremetalAction(this)" style="width: 150px;">Generate ISO</button>
|
@ -21,7 +21,7 @@
|
|||||||
{{.ClusterRows}}
|
{{.ClusterRows}}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<button type="button" class="btn btn-info" onclick="addClusterModal()">Add</button>
|
<button type="button" class="btn btn-info" id="ClusterBtn" onclick="addConfigModal(this)">Add</button>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -77,7 +77,7 @@
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</p>
|
</p>
|
||||||
<button type="button" class="btn btn-info" onclick="addContextModal()">Add</button>
|
<button type="button" class="btn btn-info" id="ContextBtn" onclick="addConfigModal(this)">Add</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- This is used by the context add modal and is injected into the DOM but not displayed except by the popup -->
|
<!-- This is used by the context add modal and is injected into the DOM but not displayed except by the popup -->
|
||||||
@ -130,7 +130,7 @@
|
|||||||
{{.CredentialRows}}
|
{{.CredentialRows}}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<button type="button" class="btn btn-info" onclick="addCredentialModal()">Add</button>
|
<button type="button" class="btn btn-info" id="CredentialBtn" onclick="addConfigModal(this)">Add</button>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
5
internal/integrations/ctl/templates/document.html
Executable file
5
internal/integrations/ctl/templates/document.html
Executable file
@ -0,0 +1,5 @@
|
|||||||
|
<h1>Airship CTL {{.Title}} Base Information</h1>
|
||||||
|
<p>Version: {{.Version}}</p>
|
||||||
|
|
||||||
|
<h2>Document Pull</h2>
|
||||||
|
<button type="button" class="btn btn-info" id="DocPullBtn" onclick="documentAction(this)" style="width: 150px;">Document Pull</button>
|
@ -39,8 +39,9 @@ var functionMap = map[configs.WsRequestType]map[configs.WsComponentType]func(con
|
|||||||
configs.Initialize: clientInit,
|
configs.Initialize: clientInit,
|
||||||
},
|
},
|
||||||
configs.AirshipCTL: {
|
configs.AirshipCTL: {
|
||||||
configs.Info: ctl.GetDefaults,
|
configs.CTLConfig: ctl.HandleConfigRequest,
|
||||||
configs.SetConfig: ctl.SetConfig,
|
configs.Baremetal: ctl.HandleBaremetalRequest,
|
||||||
|
configs.Document: ctl.HandleDocumentRequest,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
<meta name="theme-color" content="#ffffff">
|
<meta name="theme-color" content="#ffffff">
|
||||||
<script src="js/websocket.js"></script>
|
<script src="js/websocket.js"></script>
|
||||||
<script src="js/common.js"></script>
|
<script src="js/common.js"></script>
|
||||||
<script src="js/airshipctl.js"></script>
|
<script src="js/airshipctl/airshipctl.js"></script>
|
||||||
<script src="js/coreui-3.2.0/vendors/@coreui/coreui/js/coreui.bundle.min.js"></script>
|
<script src="js/coreui-3.2.0/vendors/@coreui/coreui/js/coreui.bundle.min.js"></script>
|
||||||
<link href="js/coreui-3.2.0/css/style.css" rel="stylesheet">
|
<link href="js/coreui-3.2.0/css/style.css" rel="stylesheet">
|
||||||
<link href="style.css" rel="stylesheet">
|
<link href="style.css" rel="stylesheet">
|
||||||
@ -37,7 +37,9 @@
|
|||||||
<use xlink:href="js/coreui-3.2.0/vendors/@coreui/icons/svg/free.svg#cil-airplane-mode"></use>
|
<use xlink:href="js/coreui-3.2.0/vendors/@coreui/icons/svg/free.svg#cil-airplane-mode"></use>
|
||||||
</svg> Airship</a>
|
</svg> Airship</a>
|
||||||
<ul id="AirshipDropdown" class="c-sidebar-nav-dropdown-items">
|
<ul id="AirshipDropdown" class="c-sidebar-nav-dropdown-items">
|
||||||
<li><a class="c-sidebar-nav-link" onclick="ctlGetConfig()">Config</a></span></li>
|
<li><a class="c-sidebar-nav-link" id="LiBaremetal" onclick="ctlGetDefaults(this)">Baremetal</a></span></li>
|
||||||
|
<li><a class="c-sidebar-nav-link" id="LiConfig" onclick="ctlGetDefaults(this)">Config</a></span></li>
|
||||||
|
<li><a class="c-sidebar-nav-link" id="LiDocument" onclick="ctlGetDefaults(this)">Document</a></span></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li class="c-sidebar-nav-item c-sidebar-nav-dropdown"><a
|
<li class="c-sidebar-nav-item c-sidebar-nav-dropdown"><a
|
||||||
|
66
web/js/airshipctl/airshipctl.js
Executable file
66
web/js/airshipctl/airshipctl.js
Executable file
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Splitting up scripts into sub components to keep it the functions in logical divisions
|
||||||
|
var includes = ["js/airshipctl/config.js","js/airshipctl/baremetal.js","js/airshipctl/document.js"];
|
||||||
|
|
||||||
|
// append CTL scripts to the page, this is an independent content loaded listener from the one in common.js
|
||||||
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
|
for (let include of includes) {
|
||||||
|
var script = document.createElement("script");
|
||||||
|
script.src = include;
|
||||||
|
document.head.appendChild(script);
|
||||||
|
}
|
||||||
|
}, false)
|
||||||
|
|
||||||
|
// Displays the alerts from the backend
|
||||||
|
function handleCTLResponse(json) { // eslint-disable-line no-unused-vars
|
||||||
|
if (json.hasOwnProperty("error")) {
|
||||||
|
showDismissableAlert("danger", json["error"], false);
|
||||||
|
} else {
|
||||||
|
showDismissableAlert("info", json["message"], false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function ctlGetDefaults(element) { // eslint-disable-line no-unused-vars
|
||||||
|
let id = String(element.id);
|
||||||
|
|
||||||
|
var json = { "type": "airshipctl", "subComponent": "getDefaults" };
|
||||||
|
switch(id) {
|
||||||
|
case "LiBaremetal": json = Object.assign(json, { "component": "baremetal" }); break;
|
||||||
|
case "LiConfig": json = Object.assign(json, { "component": "config" }); break;
|
||||||
|
case "LiDocument": json = Object.assign(json, { "component": "document" }); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ws.send(JSON.stringify(json));
|
||||||
|
}
|
||||||
|
|
||||||
|
function displayCTLInfo(json) { // eslint-disable-line no-unused-vars
|
||||||
|
if (json.hasOwnProperty("html")) {
|
||||||
|
document.getElementById("DashView").style.display = "none";
|
||||||
|
let div = document.getElementById("ContentDiv");
|
||||||
|
div.style.display = "";
|
||||||
|
div.innerHTML = json["html"];
|
||||||
|
} else {
|
||||||
|
if (json.hasOwnProperty("error")) {
|
||||||
|
showDismissableAlert("danger", json["error"], false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function buttonHelper(id,text,disabled) { // eslint-disable-line no-unused-vars
|
||||||
|
let button = document.getElementById(id);
|
||||||
|
button.innerText = text;
|
||||||
|
button.disabled = disabled;
|
||||||
|
}
|
34
web/js/airshipctl/baremetal.js
Executable file
34
web/js/airshipctl/baremetal.js
Executable file
@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function baremetalAction(element) { // eslint-disable-line no-unused-vars
|
||||||
|
let elementId = element.id;
|
||||||
|
|
||||||
|
// change text & disable the button while the process happens
|
||||||
|
buttonHelper(elementId, "In Progress", true);
|
||||||
|
|
||||||
|
var json = { "type": "airshipctl", "component": "baremetal" };
|
||||||
|
switch(elementId) {
|
||||||
|
case "GenIsoBtn": json = Object.assign(json, { "subComponent": "generateISO" }); break;
|
||||||
|
}
|
||||||
|
ws.send(JSON.stringify(json));
|
||||||
|
}
|
||||||
|
|
||||||
|
function ctlParseBaremetal(json) { // eslint-disable-line no-unused-vars
|
||||||
|
switch(json["subComponent"]) {
|
||||||
|
case "getDefaults": displayCTLInfo(json); break;
|
||||||
|
case "generateISO": buttonHelper("GenIsoBtn", "Generate ISO",false); handleCTLResponse(json); break;
|
||||||
|
default: handleCTLResponse(json)
|
||||||
|
}
|
||||||
|
}
|
@ -13,39 +13,26 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
function ctlGetConfig() { // eslint-disable-line no-unused-vars
|
function ctlGetConfig() { // eslint-disable-line no-unused-vars
|
||||||
console.log("Requesting airshipctl config info");
|
var json = { "type": "airshipctl", "component": "config", "subComponent": "getDefaults" };
|
||||||
var json = { "type": "airshipctl", "component": "info" };
|
|
||||||
ws.send(JSON.stringify(json));
|
ws.send(JSON.stringify(json));
|
||||||
}
|
}
|
||||||
|
|
||||||
function ctlParseConfig(json) { // eslint-disable-line no-unused-vars
|
function ctlParseConfig(json) { // eslint-disable-line no-unused-vars
|
||||||
switch(json["component"]) {
|
switch(json["subComponent"]) {
|
||||||
case "info": displayInfo(json); break;
|
case "getDefaults": displayConfigInfo(json); break;
|
||||||
default: handleCtlResponse(json);
|
default: handleCTLResponse(json);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function displayInfo(json) {
|
function displayConfigInfo(json) {
|
||||||
document.getElementById("DashView").style.display = "none";
|
displayCTLInfo(json);
|
||||||
let div = document.getElementById("ContentDiv");
|
|
||||||
div.style.display = "";
|
|
||||||
div.innerHTML = json["html"];
|
|
||||||
|
|
||||||
enableAccordion();
|
enableAccordion();
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleCtlResponse(json) {
|
|
||||||
if (json.hasOwnProperty("error")) {
|
|
||||||
showDismissableAlert("danger", json["error"], true);
|
|
||||||
} else {
|
|
||||||
showDismissableAlert("info", json["message"], true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function saveConfig(element) { // eslint-disable-line no-unused-vars
|
function saveConfig(element) { // eslint-disable-line no-unused-vars
|
||||||
var json = {
|
var json = {
|
||||||
"type": "airshipctl",
|
"type": "airshipctl",
|
||||||
"component": "setConfig",
|
"component": "config",
|
||||||
};
|
};
|
||||||
|
|
||||||
tableID = getTableId(element);
|
tableID = getTableId(element);
|
||||||
@ -59,11 +46,12 @@ function saveConfig(element) { // eslint-disable-line no-unused-vars
|
|||||||
case "CredentialTable": json = Object.assign(json, saveCredential(element)); break;
|
case "CredentialTable": json = Object.assign(json, saveCredential(element)); break;
|
||||||
case "CredentialAddTable": json = Object.assign(json, addCredential(element)); break;
|
case "CredentialAddTable": json = Object.assign(json, addCredential(element)); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ws.send(JSON.stringify(json));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log("Save Config Request: ", json);
|
||||||
|
ws.send(JSON.stringify(json));
|
||||||
}
|
}
|
||||||
|
|
||||||
function addCluster(row) {
|
function addCluster(row) {
|
||||||
@ -124,8 +112,8 @@ function addCredential(row) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveCredential(row) {
|
function saveCredential(row) {
|
||||||
return {
|
return {
|
||||||
"subComponent": "credential",
|
"subComponent": "credential",
|
||||||
"authInfoOptions": {
|
"authInfoOptions": {
|
||||||
"Name": row.cells[0].textContent,
|
"Name": row.cells[0].textContent,
|
||||||
@ -148,30 +136,20 @@ function saveConfigDialog(element) { // eslint-disable-line no-unused-vars
|
|||||||
closeDialog(element);
|
closeDialog(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This will use the cluster modal described in the pagelet that is sent via the websocket from the backend
|
// This will use the modal described in the pagelet that is sent via the websocket from the backend
|
||||||
function addClusterModal() { // eslint-disable-line no-unused-vars
|
function addConfigModal(element) { // eslint-disable-line no-unused-vars
|
||||||
let dialog = document.createElement("DIALOG");
|
let elementId = element.id;
|
||||||
document.body.appendChild(dialog);
|
var id, template;
|
||||||
dialog.setAttribute("id", "AddCluster");
|
switch(elementId) {
|
||||||
dialog.innerHTML = document.getElementById("ClusterModalTemplate").innerHTML;
|
case "ClusterBtn": id = "AddCluster"; template = "ClusterModalTemplate"; break;
|
||||||
dialog.showModal();
|
case "ContextBtn": id = "AddContext"; template = "ContextModalTemplate"; break;
|
||||||
}
|
case "CredentialBtn": id = "AddCredential"; template = "CredentialModalTemplate"; break;
|
||||||
|
}
|
||||||
|
|
||||||
// This will use the context modal described in the pagelet that is sent via the websocket from the backend
|
|
||||||
function addContextModal() { // eslint-disable-line no-unused-vars
|
|
||||||
let dialog = document.createElement("DIALOG");
|
let dialog = document.createElement("DIALOG");
|
||||||
document.body.appendChild(dialog);
|
document.body.appendChild(dialog);
|
||||||
dialog.setAttribute("id", "AddContext");
|
dialog.setAttribute("id", id);
|
||||||
dialog.innerHTML = document.getElementById("ContextModalTemplate").innerHTML;
|
dialog.innerHTML = document.getElementById(template).innerHTML;
|
||||||
dialog.showModal();
|
|
||||||
}
|
|
||||||
|
|
||||||
// This will use the context modal described in the pagelet that is sent via the websocket from the backend
|
|
||||||
function addCredentialModal() { // eslint-disable-line no-unused-vars
|
|
||||||
let dialog = document.createElement("DIALOG");
|
|
||||||
document.body.appendChild(dialog);
|
|
||||||
dialog.setAttribute("id", "AddCredential");
|
|
||||||
dialog.innerHTML = document.getElementById("CredentialModalTemplate").innerHTML;
|
|
||||||
dialog.showModal();
|
dialog.showModal();
|
||||||
}
|
}
|
||||||
|
|
34
web/js/airshipctl/document.js
Executable file
34
web/js/airshipctl/document.js
Executable file
@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function documentAction(element) { // eslint-disable-line no-unused-vars
|
||||||
|
let elementId = element.id;
|
||||||
|
|
||||||
|
// change text & disable the button while the process happens
|
||||||
|
buttonHelper(elementId, "In Progress", true);
|
||||||
|
|
||||||
|
var json = { "type": "airshipctl", "component": "document" };
|
||||||
|
switch(elementId) {
|
||||||
|
case "DocPullBtn": Object.assign(json, { "subComponent": "docPull" }); break;
|
||||||
|
}
|
||||||
|
ws.send(JSON.stringify(json));
|
||||||
|
}
|
||||||
|
|
||||||
|
function ctlParseDocument(json) { // eslint-disable-line no-unused-vars
|
||||||
|
switch(json["subComponent"]) {
|
||||||
|
case "getDefaults": displayCTLInfo(json); break;
|
||||||
|
case "docPull": buttonHelper("DocPullBtn", "Document Pull",false); handleCTLResponse(json); break;
|
||||||
|
default: handleCTLResponse(json)
|
||||||
|
}
|
||||||
|
}
|
@ -62,7 +62,7 @@ function handleMessages(message) {
|
|||||||
// create and dispatch an event based on the data received
|
// create and dispatch an event based on the data received
|
||||||
switch(json["type"]) {
|
switch(json["type"]) {
|
||||||
case "alert": showDismissableAlert(json["component"], json["message"], json["fade"]); break;
|
case "alert": showDismissableAlert(json["component"], json["message"], json["fade"]); break;
|
||||||
case "airshipctl": ctlParseConfig(json); break;
|
case "airshipctl": handleCTLMessages(json); break;
|
||||||
case "electron": hanldleElectronMessages(json); break;
|
case "electron": hanldleElectronMessages(json); break;
|
||||||
default: console.log("Received message: " + json["type"]); break;
|
default: console.log("Received message: " + json["type"]); break;
|
||||||
}
|
}
|
||||||
@ -87,6 +87,16 @@ function hanldleElectronMessages(json) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// helper function for the airshiptctl interactions
|
||||||
|
function handleCTLMessages(json) {
|
||||||
|
switch(json["component"]) {
|
||||||
|
case "config": ctlParseConfig(json); break;
|
||||||
|
case "baremetal": ctlParseBaremetal(json); break;
|
||||||
|
case "document": ctlParseDocument(json); break;
|
||||||
|
default: console.log("Received message: " + json); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function open() {
|
function open() {
|
||||||
console.log("Websocket established");
|
console.log("Websocket established");
|
||||||
var json = { "type": "electron", "component": "initialize" };
|
var json = { "type": "electron", "component": "initialize" };
|
||||||
|
Loading…
x
Reference in New Issue
Block a user