Bootstrap redfish Remote direct
This commit implements redfish remote direct subcommand under bootstrap. Change-Id: Idf97445f6fa59a77145eae1edaa15b1d22723f19 Signed-off-by: Kanwar Saad Bin Liaqat <kanwar.sbl@gmail.com>
This commit is contained in:
parent
04f75938d9
commit
3bf54274c3
@ -16,5 +16,8 @@ func NewBootstrapCommand(rootSettings *environment.AirshipCTLSettings) *cobra.Co
|
||||
ISOGenCmd := NewISOGenCommand(bootstrapRootCmd, rootSettings)
|
||||
bootstrapRootCmd.AddCommand(ISOGenCmd)
|
||||
|
||||
remoteDirectCmd := NewRemoteDirectCommand(rootSettings)
|
||||
bootstrapRootCmd.AddCommand(remoteDirectCmd)
|
||||
|
||||
return bootstrapRootCmd
|
||||
}
|
||||
|
73
cmd/bootstrap/bootstrap_remotedirect.go
Normal file
73
cmd/bootstrap/bootstrap_remotedirect.go
Normal file
@ -0,0 +1,73 @@
|
||||
package bootstrap
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"opendev.org/airship/airshipctl/pkg/environment"
|
||||
alog "opendev.org/airship/airshipctl/pkg/log"
|
||||
remote "opendev.org/airship/airshipctl/pkg/remote"
|
||||
)
|
||||
|
||||
// RemoteDirect settings for remotedirect command
|
||||
type RemoteDirectSettings struct {
|
||||
*environment.AirshipCTLSettings
|
||||
|
||||
RemoteConfig remote.RemoteDirectConfig
|
||||
}
|
||||
|
||||
// InitFlags adds flags and their default settings for Remote Direct command
|
||||
func (cmdSetting *RemoteDirectSettings) InitFlags(cmd *cobra.Command) {
|
||||
flags := cmd.Flags()
|
||||
|
||||
// TODO: Remove CLI flags after reading configuration from config documents
|
||||
// ========================================================================
|
||||
flags.StringVar(&cmdSetting.RemoteConfig.RemoteURL,
|
||||
"remote-url",
|
||||
"http://localhost:8000",
|
||||
"[Temporary. Will be removed] Remote Redfish/Smash URL")
|
||||
|
||||
flags.StringVar(&cmdSetting.RemoteConfig.EphemeralNodeId,
|
||||
"eph-node-id",
|
||||
"",
|
||||
"[Temporary. Will be removed] Ephemeral Node ID")
|
||||
|
||||
flags.StringVar(&cmdSetting.RemoteConfig.IsoPath,
|
||||
"iso-path",
|
||||
"",
|
||||
"[Temporary. Will be removed] Remote ISO path for ephemeral node")
|
||||
|
||||
flags.StringVar(&cmdSetting.RemoteConfig.RemoteType,
|
||||
"remote-type",
|
||||
"redfish",
|
||||
"Remote type e.g. redfish, smash etc.")
|
||||
|
||||
err := cmd.MarkFlagRequired("eph-node-id")
|
||||
if err != nil {
|
||||
alog.Fatal(err)
|
||||
}
|
||||
|
||||
err = cmd.MarkFlagRequired("iso-path")
|
||||
if err != nil {
|
||||
alog.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// New Bootstrap remote direct subcommand
|
||||
func NewRemoteDirectCommand(rootSettings *environment.AirshipCTLSettings) *cobra.Command {
|
||||
settings := &RemoteDirectSettings{AirshipCTLSettings: rootSettings}
|
||||
remoteDirect := &cobra.Command{
|
||||
Use: "remotedirect",
|
||||
Short: "Bootstrap ephemeral node",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
|
||||
/* TODO: Get config from settings.GetCurrentContext() and remove cli arguments */
|
||||
|
||||
/* Trigger remotedirect based on remote type */
|
||||
return remote.DoRemoteDirect(settings.RemoteConfig)
|
||||
},
|
||||
}
|
||||
|
||||
settings.InitFlags(remoteDirect)
|
||||
|
||||
return remoteDirect
|
||||
}
|
20
cmd/bootstrap/bootstrap_remotedirect_test.go
Normal file
20
cmd/bootstrap/bootstrap_remotedirect_test.go
Normal file
@ -0,0 +1,20 @@
|
||||
package bootstrap
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"opendev.org/airship/airshipctl/testutil"
|
||||
)
|
||||
|
||||
func TestRemoteDirect(t *testing.T) {
|
||||
tests := []*testutil.CmdTest{
|
||||
{
|
||||
Name: "remotedirect-cmd-with-help",
|
||||
CmdLine: "remotedirect --help",
|
||||
Cmd: NewRemoteDirectCommand(nil),
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
testutil.RunTest(t, tt)
|
||||
}
|
||||
}
|
@ -4,8 +4,9 @@ Usage:
|
||||
bootstrap [command]
|
||||
|
||||
Available Commands:
|
||||
help Help about any command
|
||||
isogen Generate bootstrap ISO image
|
||||
help Help about any command
|
||||
isogen Generate bootstrap ISO image
|
||||
remotedirect Bootstrap ephemeral node
|
||||
|
||||
Flags:
|
||||
-h, --help help for bootstrap
|
||||
|
11
cmd/bootstrap/testdata/TestRemoteDirectGoldenOutput/remotedirect-cmd-with-help.golden
vendored
Normal file
11
cmd/bootstrap/testdata/TestRemoteDirectGoldenOutput/remotedirect-cmd-with-help.golden
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
Bootstrap ephemeral node
|
||||
|
||||
Usage:
|
||||
remotedirect [flags]
|
||||
|
||||
Flags:
|
||||
--eph-node-id string [Temporary. Will be removed] Ephemeral Node ID
|
||||
-h, --help help for remotedirect
|
||||
--iso-path string [Temporary. Will be removed] Remote ISO path for ephemeral node
|
||||
--remote-type string Remote type e.g. redfish, smash etc. (default "redfish")
|
||||
--remote-url string [Temporary. Will be removed] Remote Redfish/Smash URL (default "http://localhost:8000")
|
2
go.mod
2
go.mod
@ -7,6 +7,8 @@ require (
|
||||
github.com/Azure/go-autorest/autorest v0.2.0 // indirect
|
||||
github.com/MakeNowJust/heredoc v0.0.0-20171113091838-e9091a26100e // indirect
|
||||
github.com/Microsoft/go-winio v0.4.12 // indirect
|
||||
github.com/Nordix/go-redfish v0.0.0-20191016123452-b7790941aa86
|
||||
github.com/Nordix/go-redfish/client v0.0.0-20191016123452-b7790941aa86
|
||||
github.com/argoproj/argo v2.3.0+incompatible
|
||||
github.com/argoproj/pkg v0.0.0-20190409001913-7e3ef65c8d44 // indirect
|
||||
github.com/blang/semver v3.5.1+incompatible // indirect
|
||||
|
59
go.sum
59
go.sum
@ -1,10 +1,8 @@
|
||||
cloud.google.com/go v0.26.0 h1:e0WKqKTd5BnrG8aKH3J3h+QvEIQtSUcf2n5UZ5ZgLtQ=
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.34.0 h1:eOI3/cP2VTU6uZLDYAoic+eyzzB9YyGmJ7eIjl8rOPg=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
contrib.go.opencensus.io/exporter/ocagent v0.4.12 h1:jGFvw3l57ViIVEPKKEUXPcLYIXJmQxLUh6ey1eJhwyc=
|
||||
contrib.go.opencensus.io/exporter/ocagent v0.4.12/go.mod h1:450APlNTSR6FrvC3CTRqYosuDstRB9un7SOx2k/9ckA=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
|
||||
github.com/Azure/go-autorest/autorest v0.2.0 h1:zBtSTOQTtjzHVRe+mhkiHvHwRTKHhjBEyo1m6DfI3So=
|
||||
github.com/Azure/go-autorest/autorest v0.2.0/go.mod h1:AKyIcETwSUFxIcs/Wnq/C+kwCtlEYGUVd7FPNb2slmg=
|
||||
@ -12,7 +10,6 @@ github.com/Azure/go-autorest/autorest/adal v0.1.0 h1:RSw/7EAullliqwkZvgIGDYZWQm1
|
||||
github.com/Azure/go-autorest/autorest/adal v0.1.0/go.mod h1:MeS4XhScH55IST095THyTxElntu7WqB7pNbZo8Q5G3E=
|
||||
github.com/Azure/go-autorest/autorest/date v0.1.0 h1:YGrhWfrgtFs84+h0o46rJrlmsZtyZRg470CqAXTZaGM=
|
||||
github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA=
|
||||
github.com/Azure/go-autorest/autorest/mocks v0.1.0 h1:Kx+AUU2Te+A3JIyYn6Dfs+cFgx5XorQKuIXrZGoq/SI=
|
||||
github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
|
||||
github.com/Azure/go-autorest/logger v0.1.0 h1:ruG4BSDXONFRrZZJ2GUXDiUyVpayPmb1GnWeHDdaNKY=
|
||||
github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=
|
||||
@ -22,9 +19,12 @@ github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/MakeNowJust/heredoc v0.0.0-20171113091838-e9091a26100e h1:eb0Pzkt15Bm7f2FFYv7sjY7NPFi3cPkS3tv1CcrFBWA=
|
||||
github.com/MakeNowJust/heredoc v0.0.0-20171113091838-e9091a26100e/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E=
|
||||
github.com/Microsoft/go-winio v0.4.12 h1:xAfWHN1IrQ0NJ9TBC0KBZoqLjzDTr1ML+4MywiUOryc=
|
||||
github.com/Microsoft/go-winio v0.4.12/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
|
||||
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
|
||||
github.com/Nordix/go-redfish v0.0.0-20191016123452-b7790941aa86 h1:+Myox4ydvtWzVSnvF/ZjABEA7RDiPRgE3sS5u4oQsHk=
|
||||
github.com/Nordix/go-redfish v0.0.0-20191016123452-b7790941aa86/go.mod h1:xlgfxiVLo/0lxBF98IhyCkAboUX27SOXieV1LsbyA30=
|
||||
github.com/Nordix/go-redfish/client v0.0.0-20191016123452-b7790941aa86 h1:Frmy6I0XnpsCrM+FFrXq3354M3dVSrR+fFGIGb3fxXk=
|
||||
github.com/Nordix/go-redfish/client v0.0.0-20191016123452-b7790941aa86/go.mod h1:44cqm4BYTmR3MAfUFZmYYOXZ4S9rDr8QM6MlQagq4M8=
|
||||
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
|
||||
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
@ -54,15 +54,11 @@ github.com/cheekybits/genny v0.0.0-20170328200008-9127e812e1e9/go.mod h1:+tQajlR
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/colinmarc/hdfs v0.0.0-20180802165501-48eb8d6c34a9 h1:hJqIlFDcaaBLEBkCuqyEtzSsloo/h+lm08Qrq1OM/e8=
|
||||
github.com/colinmarc/hdfs v0.0.0-20180802165501-48eb8d6c34a9/go.mod h1:0DumPviB681UcSuJErAbDIOx6SIaJWj463TymfZG02I=
|
||||
github.com/coreos/bbolt v1.3.2 h1:wZwiHHUieZCquLkDL0B8UhzreNWsPHooDAG3q34zk0s=
|
||||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||
github.com/coreos/etcd v3.3.13+incompatible h1:8F3hqu9fGYLBifCmRCJsicFqDx/D68Rt3q1JMazcgBQ=
|
||||
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM=
|
||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e h1:Wf6HqHfScWJN9/ZjdUKyjop4mf3Qdd+1TvvltAvM3m8=
|
||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg=
|
||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
@ -89,11 +85,8 @@ github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25Kn
|
||||
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
|
||||
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
||||
github.com/elazarl/goproxy v0.0.0-20190421051319-9d40249d3c2f h1:8GDPb0tCY8LQ+OJ3dbHb5sA6YZWXFORQYZx5sdsTlMs=
|
||||
github.com/elazarl/goproxy v0.0.0-20190421051319-9d40249d3c2f/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
|
||||
github.com/elazarl/goproxy/ext v0.0.0-20190421051319-9d40249d3c2f h1:AUj1VoZUfhPhOPHULCQQDnGhRelpFWHMLhQVWDsS0v4=
|
||||
github.com/elazarl/goproxy/ext v0.0.0-20190421051319-9d40249d3c2f/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8=
|
||||
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633 h1:H2pdYOb3KQ1/YsqVWoWNLQO+fusocsw354rqGTZtAgw=
|
||||
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
||||
github.com/emicklei/go-restful v2.9.6+incompatible h1:tfrHha8zJ01ywiOEC1miGY8st1/igzWB8OmvPgoYX7w=
|
||||
github.com/emicklei/go-restful v2.9.6+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
||||
@ -107,7 +100,6 @@ github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI
|
||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32 h1:Mn26/9ZMNWSw9C9ERFA1PUxfmGpolnw2v0bKOREu5ew=
|
||||
github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32/go.mod h1:GIjDIg/heH5DOkXY3YJ/wNhfHsQHoXGjl8G8amsYQ1I=
|
||||
@ -131,11 +123,9 @@ github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a
|
||||
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef h1:veQD95Isof8w9/WXiA+pa3tz3fJXkt5B7QaRBrM62gk=
|
||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/mock v1.1.1 h1:G5FRp8JnTd7RQH5kemVNlMeyXQAztQ3mOWV95KxsXH8=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.2.0 h1:28o5sBqPkBsMGnC6b4MvE2TzSr5/AT4c/1fLqVGIwlk=
|
||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
@ -144,15 +134,11 @@ github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y
|
||||
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golangplus/bytes v0.0.0-20160111154220-45c989fe5450 h1:7xqw01UYS+KCI25bMrPxwNYkSns2Db1ziQPpVq99FpE=
|
||||
github.com/golangplus/bytes v0.0.0-20160111154220-45c989fe5450/go.mod h1:Bk6SMAONeMXrxql8uvOKuAZSu8aM5RUGv+1C6IJaEho=
|
||||
github.com/golangplus/fmt v0.0.0-20150411045040-2a5d6d7d2995 h1:f5gsjBiF9tRRVomCvrkGMMWI8W1f2OBFar2c5oakAP0=
|
||||
github.com/golangplus/fmt v0.0.0-20150411045040-2a5d6d7d2995/go.mod h1:lJgMEyOkYFkPcDKwRXegd+iM6E7matEszMG5HhwytU8=
|
||||
github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e h1:KhcknUwkWHKZPbFy2P7jH5LKJ3La+0ZeknkkmrSgqb0=
|
||||
github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e/go.mod h1:0AA//k/eakGydO4jKRoRL2j92ZKSzTgj9tclaCrvXHk=
|
||||
github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
|
||||
github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
|
||||
@ -167,15 +153,12 @@ github.com/gophercloud/gophercloud v0.1.0 h1:P/nh25+rzXouhytV2pUHBb65fnds26Ghl8/
|
||||
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
|
||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/mux v1.7.2 h1:zoNxOV7WjqXptQOVngLmcSQgXmgk4NMz1HibBchjl/I=
|
||||
github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
|
||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/gregjones/httpcache v0.0.0-20190212212710-3befbb6ad0cc h1:f8eY6cV/x1x+HLjOp4r72s/31/V2aTUtg5oKRRPf8/Q=
|
||||
github.com/gregjones/httpcache v0.0.0-20190212212710-3befbb6ad0cc/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0 h1:Iju5GlWwrvL6UBg4zJJt3btmonfrMlCDdsejg4CZE7c=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.8.5 h1:2+KSC78XiO6Qy0hIjfc1OD9H+hsaJdJlb8Kqsd41CTE=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
@ -185,11 +168,9 @@ github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/b
|
||||
github.com/hashicorp/golang-lru v0.0.0-20180201235237-0fb14efe8c47/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/imdario/mergo v0.3.7 h1:Y+UAYTZ7gDEuOfhxKWy+dvb5dRQ6rJjFSdX2HZY1/gI=
|
||||
github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/jcmturner/gofork v0.0.0-20190328161633-dc7c13fece03 h1:FUwcHNlEqkqLjLBdCp5PRlCFijNjvcYANOZXzCfXwCM=
|
||||
github.com/jcmturner/gofork v0.0.0-20190328161633-dc7c13fece03/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o=
|
||||
@ -204,14 +185,11 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW
|
||||
github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k=
|
||||
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0=
|
||||
@ -240,7 +218,6 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ
|
||||
github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c h1:nXxl5PrvVm2L/wCy8dQu6DMTwH4oIuGN8GJDAlqDdVE=
|
||||
github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
||||
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
@ -249,26 +226,21 @@ github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+
|
||||
github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0=
|
||||
github.com/naoina/toml v0.1.1/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E=
|
||||
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.6.0 h1:Ix8l273rp3QzYgXSR+c8d1fTG7UPgYkOSELPhiY/YGw=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w=
|
||||
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo=
|
||||
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ=
|
||||
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||
github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=
|
||||
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
|
||||
github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g=
|
||||
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
||||
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||
github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
@ -292,11 +264,9 @@ github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYe
|
||||
github.com/russross/blackfriday v0.0.0-20170610170232-067529f716f4/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||
github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo=
|
||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||
github.com/sirupsen/logrus v1.2.0 h1:juTguoYk5qI21pwyTXY3B3Y5cOTH3ZUyZCg1v/mihuo=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k=
|
||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||
github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E=
|
||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc=
|
||||
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
|
||||
@ -311,11 +281,9 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
|
||||
github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
|
||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||
github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 h1:LnC5Kc/wtumK+WB441p7ynQJzVuNRJiqddSIE3IlSEQ=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
@ -325,20 +293,14 @@ github.com/vishvananda/netlink v0.0.0-20171020171820-b2de5d10e38e h1:f1yevOHP+Su
|
||||
github.com/vishvananda/netlink v0.0.0-20171020171820-b2de5d10e38e/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk=
|
||||
github.com/vishvananda/netns v0.0.0-20171111001504-be1fbeda1936 h1:J9gO8RJCAFlln1jsvRba/CWVUnMHwObklfxxjErl1uk=
|
||||
github.com/vishvananda/netns v0.0.0-20171111001504-be1fbeda1936/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/xlab/handysort v0.0.0-20150421192137-fb3537ed64a1 h1:j2hhcujLRHAg872RWAV5yaUrEjHEObwDv3aImCaNLek=
|
||||
github.com/xlab/handysort v0.0.0-20150421192137-fb3537ed64a1/go.mod h1:QcJo0QPSfTONNIgpN5RA8prR7fF8nkF6cTWTcNerRO8=
|
||||
go.etcd.io/bbolt v1.3.2 h1:Z/90sZLPOeCy2PwprqkFa25PdkusRzaj9P8zm/KNyvk=
|
||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||
go.opencensus.io v0.20.2 h1:NAfh7zF0/3/HqtMvJNZ/RFrSlCE6ZTlHmKfhL/Dm1Jk=
|
||||
go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||
go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM=
|
||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
@ -366,10 +328,9 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
|
||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421 h1:Wo7BWFiOk0QRFMLYMqJGFMd9CgUAcGx7V+qEg/h5IBI=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@ -394,7 +355,6 @@ golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20190621203818-d432491b9138 h1:t8BZD9RDjkm9/h7yYN6kE8oaeov5r9aztkB7zKA5Tkg=
|
||||
golang.org/x/sys v0.0.0-20190621203818-d432491b9138/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
@ -411,7 +371,6 @@ golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgw
|
||||
google.golang.org/api v0.3.1 h1:oJra/lMfmtm13/rgY/8i3MzjFWYXvQIAKjQ3HqofMk8=
|
||||
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19 h1:Lj2SnHtxkRGJDqnGaSjo+CCdIieEnwVazbOXILwQemk=
|
||||
@ -422,9 +381,7 @@ google.golang.org/grpc v1.19.1 h1:TrBcJ1yqAl1G++wO39nD/qtgpsW9/1+QGrluyMGEYgM=
|
||||
google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
|
||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||
@ -432,7 +389,6 @@ gopkg.in/jcmturner/aescts.v1 v1.0.1 h1:cVVZBK2b1zY26haWB4vbBiZrfFQnfbTVrE3xZq6hr
|
||||
gopkg.in/jcmturner/aescts.v1 v1.0.1/go.mod h1:nsR8qBOg+OucoIW+WMhB3GspUQXq9XorLnQb9XtvcOo=
|
||||
gopkg.in/jcmturner/dnsutils.v1 v1.0.1 h1:cIuC1OLRGZrld+16ZJvvZxVJeKPsvd5eUIvxfoN5hSM=
|
||||
gopkg.in/jcmturner/dnsutils.v1 v1.0.1/go.mod h1:m3v+5svpVOhtFAP/wSz+yzh4Mc0Fg7eRhxkJMWSIz9Q=
|
||||
gopkg.in/jcmturner/goidentity.v2 v2.0.0 h1:6Bmcdaxb0dD3HyHbo/MtJ2Q1wXLDuZJFwXZmuZvM+zw=
|
||||
gopkg.in/jcmturner/goidentity.v2 v2.0.0/go.mod h1:vCwK9HeXksMeUmQ4SxDd1tRz4LejrKh3KRVjQWhjvZI=
|
||||
gopkg.in/jcmturner/gokrb5.v5 v5.3.0 h1:RS1MYApX27Hx1Xw7NECs7XxGxxrm69/4OmaRuX9kwec=
|
||||
gopkg.in/jcmturner/gokrb5.v5 v5.3.0/go.mod h1:oQz8Wc5GsctOTgCVyKad1Vw4TCWz5G6gfIQr88RPv4k=
|
||||
@ -443,14 +399,11 @@ gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24
|
||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||
gopkg.in/square/go-jose.v2 v2.2.2 h1:orlkJ3myw8CN1nVQHBFfloD+L3egixIa4FvUP6RosSA=
|
||||
gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
|
||||
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
@ -475,10 +428,8 @@ k8s.io/cluster-bootstrap v0.0.0-20190516232516-d7d78ab2cfe7 h1:5wvjieVoU4oovHlke
|
||||
k8s.io/cluster-bootstrap v0.0.0-20190516232516-d7d78ab2cfe7/go.mod h1:iBSm2nwo3OaiuW8VDvc3ySDXK5SKfUrxwPvBloKG7zg=
|
||||
k8s.io/component-base v0.0.0-20190516230545-9b07ebd4193b h1:uGhPlhc5zuKFBhA2A94CFQjr1R9gz3u65BQFGqcV+rE=
|
||||
k8s.io/component-base v0.0.0-20190516230545-9b07ebd4193b/go.mod h1:DMaomcf3j3MM2j1FsvlLVVlc7wA2jPytEur3cP9zRxQ=
|
||||
k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6 h1:4s3/R4+OYYYUKptXPhZKjQ04WJ6EhQQVFdjOFvCazDk=
|
||||
k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
||||
k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
|
||||
k8s.io/klog v0.3.0 h1:0VPpR+sizsiivjIfIAQH/rl8tan6jvWkS7lU+0di3lE=
|
||||
k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
|
||||
k8s.io/klog v0.3.3 h1:niceAagH1tzskmaie/icWd7ci1wbG7Bf2c6YGcQv+3c=
|
||||
k8s.io/klog v0.3.3/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
|
||||
|
14
pkg/error/error.go
Normal file
14
pkg/error/error.go
Normal file
@ -0,0 +1,14 @@
|
||||
package error
|
||||
|
||||
// AirshipError is the base error type
|
||||
// used to create extended error types
|
||||
// in other airshipctl packages.
|
||||
type AirshipError struct {
|
||||
Message string
|
||||
}
|
||||
|
||||
// Error function implments the golang
|
||||
// error interface
|
||||
func (ae *AirshipError) Error() string {
|
||||
return ae.Message
|
||||
}
|
17
pkg/remote/errors.go
Normal file
17
pkg/remote/errors.go
Normal file
@ -0,0 +1,17 @@
|
||||
package remote
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
aerror "opendev.org/airship/airshipctl/pkg/error"
|
||||
)
|
||||
|
||||
type RemoteDirectError struct {
|
||||
aerror.AirshipError
|
||||
}
|
||||
|
||||
func NewRemoteDirectErrorf(format string, v ...interface{}) error {
|
||||
e := &RemoteDirectError{}
|
||||
e.Message = fmt.Sprintf(format, v...)
|
||||
return e
|
||||
}
|
42
pkg/remote/redfish/errors.go
Normal file
42
pkg/remote/redfish/errors.go
Normal file
@ -0,0 +1,42 @@
|
||||
package redfish
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
aerror "opendev.org/airship/airshipctl/pkg/error"
|
||||
)
|
||||
|
||||
type RedfishClientError struct {
|
||||
aerror.AirshipError
|
||||
}
|
||||
|
||||
func NewRedfishClientErrorf(format string, v ...interface{}) error {
|
||||
e := &RedfishClientError{}
|
||||
e.Message = fmt.Sprintf(format, v...)
|
||||
return e
|
||||
}
|
||||
|
||||
type RedfishConfigError struct {
|
||||
aerror.AirshipError
|
||||
}
|
||||
|
||||
func NewRedfishConfigErrorf(format string, v ...interface{}) error {
|
||||
e := &RedfishConfigError{}
|
||||
e.Message = fmt.Sprintf(format, v...)
|
||||
return e
|
||||
}
|
||||
|
||||
// Redfish client return error if response has no body.
|
||||
// In this case this function further checks the
|
||||
// HTTP response code.
|
||||
func ScreenRedfishError(httpResp *http.Response, err error) error {
|
||||
if err != nil && httpResp != nil {
|
||||
if httpResp.StatusCode < 200 || httpResp.StatusCode >= 400 {
|
||||
return NewRedfishClientErrorf("%s", err.Error())
|
||||
}
|
||||
} else if err != nil {
|
||||
return NewRedfishClientErrorf("%s", err.Error())
|
||||
}
|
||||
return nil
|
||||
}
|
127
pkg/remote/redfish/redfish.go
Normal file
127
pkg/remote/redfish/redfish.go
Normal file
@ -0,0 +1,127 @@
|
||||
package redfish
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/url"
|
||||
|
||||
redfishApi "github.com/Nordix/go-redfish/api"
|
||||
redfishClient "github.com/Nordix/go-redfish/client"
|
||||
|
||||
alog "opendev.org/airship/airshipctl/pkg/log"
|
||||
)
|
||||
|
||||
type RedfishRemoteDirect struct {
|
||||
|
||||
// Context
|
||||
Context context.Context
|
||||
|
||||
// remote URL
|
||||
RemoteURL url.URL
|
||||
|
||||
// ephemeral Host ID
|
||||
EphemeralNodeId string
|
||||
|
||||
// ISO URL
|
||||
IsoPath string
|
||||
|
||||
// Redfish Client implementation
|
||||
Api redfishApi.RedfishAPI
|
||||
}
|
||||
|
||||
// Top level function to handle Redfish remote direct
|
||||
func (cfg RedfishRemoteDirect) DoRemoteDirect() error {
|
||||
|
||||
alog.Debugf("Using Redfish Endpoint: '%s'", cfg.RemoteURL.String())
|
||||
|
||||
/* TODO: Add Authentication when redfish library supports it. */
|
||||
|
||||
/* Get system details */
|
||||
systemId := cfg.EphemeralNodeId
|
||||
system, _, err := cfg.Api.GetSystem(cfg.Context, systemId)
|
||||
if err != nil {
|
||||
return NewRedfishClientErrorf("Get System[%s] failed with err: %s", systemId, err.Error())
|
||||
}
|
||||
alog.Debugf("Ephemeral Node System ID: '%s'", systemId)
|
||||
|
||||
/* get manager for system */
|
||||
managerId, err := GetResourceIDFromURL(system.Links.ManagedBy[0].OdataId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
alog.Debugf("Ephemeral node managerId: '%s'", managerId)
|
||||
|
||||
/* Get manager's Cd or DVD virtual media ID */
|
||||
vMediaId, vMediaType, err := GetVirtualMediaId(cfg.Context, cfg.Api, managerId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
alog.Debugf("Ephemeral Node Virtual Media Id: '%s'", vMediaId)
|
||||
|
||||
/* Load ISO in manager's virtual media */
|
||||
err = SetVirtualMedia(cfg.Context, cfg.Api, managerId, vMediaId, cfg.IsoPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
alog.Debugf("Successfully loaded virtual media: '%s'", cfg.IsoPath)
|
||||
|
||||
/* Set system's bootsource to selected media */
|
||||
err = SetSystemBootSourceForMediaType(cfg.Context, cfg.Api, systemId, vMediaType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
/* Reboot system */
|
||||
err = RebootSystem(cfg.Context, cfg.Api, systemId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
alog.Debug("Restarted ephemeral host")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Creates a new Redfish remote direct client.
|
||||
func NewRedfishRemoteDirectClient(ctx context.Context,
|
||||
remoteURL string,
|
||||
ephNodeID string,
|
||||
isoPath string,
|
||||
) (RedfishRemoteDirect, error) {
|
||||
|
||||
if remoteURL == "" {
|
||||
return RedfishRemoteDirect{},
|
||||
NewRedfishConfigErrorf("redfish remote url empty")
|
||||
}
|
||||
|
||||
if ephNodeID == "" {
|
||||
return RedfishRemoteDirect{},
|
||||
NewRedfishConfigErrorf("redfish ephemeral node id empty")
|
||||
}
|
||||
|
||||
if isoPath == "" {
|
||||
return RedfishRemoteDirect{},
|
||||
NewRedfishConfigErrorf("redfish ephemeral node iso Path empty")
|
||||
}
|
||||
|
||||
cfg := &redfishClient.Configuration{
|
||||
BasePath: remoteURL,
|
||||
DefaultHeader: make(map[string]string),
|
||||
UserAgent: "airshipctl/client",
|
||||
}
|
||||
|
||||
var api redfishApi.RedfishAPI = redfishClient.NewAPIClient(cfg).DefaultApi
|
||||
|
||||
url, err := url.Parse(remoteURL)
|
||||
if err != nil {
|
||||
return RedfishRemoteDirect{}, NewRedfishConfigErrorf("Invalid URL format: %v", err)
|
||||
}
|
||||
|
||||
client := RedfishRemoteDirect{
|
||||
Context: ctx,
|
||||
RemoteURL: *url,
|
||||
EphemeralNodeId: ephNodeID,
|
||||
IsoPath: isoPath,
|
||||
Api: api,
|
||||
}
|
||||
|
||||
return client, nil
|
||||
}
|
266
pkg/remote/redfish/redfish_test.go
Normal file
266
pkg/remote/redfish/redfish_test.go
Normal file
@ -0,0 +1,266 @@
|
||||
package redfish_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
redfishAPI "github.com/Nordix/go-redfish/api"
|
||||
redfishMocks "github.com/Nordix/go-redfish/api/mocks"
|
||||
redfishClient "github.com/Nordix/go-redfish/client"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
|
||||
. "opendev.org/airship/airshipctl/pkg/remote/redfish"
|
||||
)
|
||||
|
||||
const (
|
||||
computerSystemID = "server-100"
|
||||
)
|
||||
|
||||
var (
|
||||
ctx = context.Background()
|
||||
defaultURL = "https://localhost:1234"
|
||||
|
||||
SampleSystem = redfishClient.ComputerSystem{
|
||||
Id: computerSystemID,
|
||||
Name: "server-100",
|
||||
UUID: "58893887-8974-2487-2389-841168418919",
|
||||
Status: redfishClient.Status{
|
||||
State: "Enabled",
|
||||
Health: "OK",
|
||||
},
|
||||
Links: redfishClient.SystemLinks{
|
||||
ManagedBy: []redfishClient.IdRef{
|
||||
{OdataId: "/redfish/v1/Managers/manager-1"},
|
||||
},
|
||||
},
|
||||
Boot: redfishClient.Boot{
|
||||
BootSourceOverrideTarget: redfishClient.BOOTSOURCE_CD,
|
||||
BootSourceOverrideEnabled: redfishClient.BOOTSOURCEOVERRIDEENABLED_CONTINUOUS,
|
||||
BootSourceOverrideTargetRedfishAllowableValues: []redfishClient.BootSource{
|
||||
redfishClient.BOOTSOURCE_CD,
|
||||
redfishClient.BOOTSOURCE_FLOPPY,
|
||||
redfishClient.BOOTSOURCE_HDD,
|
||||
redfishClient.BOOTSOURCE_PXE,
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func getDefaultRedfishRemoteDirectObj(t *testing.T, api redfishAPI.RedfishAPI) RedfishRemoteDirect {
|
||||
|
||||
t.Helper()
|
||||
|
||||
rDCfg, err := NewRedfishRemoteDirectClient(
|
||||
ctx,
|
||||
defaultURL,
|
||||
computerSystemID,
|
||||
"/tmp/test.iso",
|
||||
)
|
||||
|
||||
assert.NoError(t, err)
|
||||
|
||||
rDCfg.Api = api
|
||||
|
||||
return rDCfg
|
||||
}
|
||||
|
||||
func TestRedfishRemoteDirectNormal(t *testing.T) {
|
||||
|
||||
m := &redfishMocks.RedfishAPI{}
|
||||
defer m.AssertExpectations(t)
|
||||
|
||||
systemID := computerSystemID
|
||||
m.On("GetSystem", ctx, systemID).
|
||||
Return(SampleSystem, nil, nil)
|
||||
m.On("InsertVirtualMedia", ctx, "manager-1", "Cd", mock.Anything).
|
||||
Return(redfishClient.RedfishError{}, nil, nil)
|
||||
|
||||
systemReq := redfishClient.ComputerSystem{
|
||||
Boot: redfishClient.Boot{
|
||||
BootSourceOverrideTarget: redfishClient.BOOTSOURCE_CD,
|
||||
},
|
||||
}
|
||||
m.On("SetSystem", ctx, systemID, systemReq).
|
||||
Times(1).
|
||||
Return(redfishClient.ComputerSystem{}, nil, nil)
|
||||
|
||||
resetReq := redfishClient.ResetRequestBody{}
|
||||
resetReq.ResetType = redfishClient.RESETTYPE_FORCE_OFF
|
||||
m.On("ResetSystem", ctx, systemID, resetReq).
|
||||
Times(1).
|
||||
Return(redfishClient.RedfishError{}, nil, nil)
|
||||
|
||||
resetReq.ResetType = redfishClient.RESETTYPE_ON
|
||||
m.On("ResetSystem", ctx, systemID, resetReq).
|
||||
Times(1).
|
||||
Return(redfishClient.RedfishError{}, nil, nil)
|
||||
|
||||
rDCfg := getDefaultRedfishRemoteDirectObj(t, m)
|
||||
|
||||
err := rDCfg.DoRemoteDirect()
|
||||
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestRedfishRemoteDirectInvalidSystemId(t *testing.T) {
|
||||
|
||||
m := &redfishMocks.RedfishAPI{}
|
||||
defer m.AssertExpectations(t)
|
||||
|
||||
systemID := "invalid-server"
|
||||
localRDCfg := getDefaultRedfishRemoteDirectObj(t, m)
|
||||
|
||||
localRDCfg.EphemeralNodeId = systemID
|
||||
|
||||
realErr := fmt.Errorf("%s system do not exist", systemID)
|
||||
m.On("GetSystem", ctx, systemID).
|
||||
Times(1).
|
||||
Return(redfishClient.ComputerSystem{}, nil, realErr)
|
||||
|
||||
err := localRDCfg.DoRemoteDirect()
|
||||
|
||||
_, ok := err.(*RedfishClientError)
|
||||
assert.True(t, ok)
|
||||
}
|
||||
|
||||
func TestRedfishRemoteDirectGetSystemNetworkError(t *testing.T) {
|
||||
|
||||
m := &redfishMocks.RedfishAPI{}
|
||||
defer m.AssertExpectations(t)
|
||||
|
||||
systemID := computerSystemID
|
||||
realErr := fmt.Errorf("Server request timeout")
|
||||
httpResp := &http.Response{
|
||||
StatusCode: 408,
|
||||
}
|
||||
m.On("GetSystem", ctx, systemID).
|
||||
Times(1).
|
||||
Return(redfishClient.ComputerSystem{}, httpResp, realErr)
|
||||
|
||||
rDCfg := getDefaultRedfishRemoteDirectObj(t, m)
|
||||
|
||||
err := rDCfg.DoRemoteDirect()
|
||||
|
||||
_, ok := err.(*RedfishClientError)
|
||||
assert.True(t, ok)
|
||||
}
|
||||
|
||||
func TestRedfishRemoteDirectInvalidIsoPath(t *testing.T) {
|
||||
|
||||
m := &redfishMocks.RedfishAPI{}
|
||||
defer m.AssertExpectations(t)
|
||||
|
||||
systemID := computerSystemID
|
||||
rDCfg := getDefaultRedfishRemoteDirectObj(t, m)
|
||||
localRDCfg := rDCfg
|
||||
localRDCfg.IsoPath = "bogus/path/to.iso"
|
||||
|
||||
errStr := "Invalid remote boot path"
|
||||
realErr := fmt.Errorf(errStr)
|
||||
httpResp := &http.Response{
|
||||
StatusCode: 500,
|
||||
}
|
||||
m.On("GetSystem", ctx, systemID).
|
||||
Times(1).
|
||||
Return(SampleSystem, nil, nil)
|
||||
|
||||
m.On("InsertVirtualMedia", ctx, "manager-1", "Cd", mock.Anything).
|
||||
Return(redfishClient.RedfishError{}, httpResp, realErr)
|
||||
|
||||
err := localRDCfg.DoRemoteDirect()
|
||||
|
||||
_, ok := err.(*RedfishClientError)
|
||||
assert.True(t, ok)
|
||||
}
|
||||
|
||||
func TestRedfishRemoteDirectCdDvdNotAvailableInBootSources(t *testing.T) {
|
||||
|
||||
m := &redfishMocks.RedfishAPI{}
|
||||
defer m.AssertExpectations(t)
|
||||
|
||||
systemID := computerSystemID
|
||||
invalidSystem := SampleSystem
|
||||
invalidSystem.Boot.BootSourceOverrideTargetRedfishAllowableValues = []redfishClient.BootSource{
|
||||
redfishClient.BOOTSOURCE_HDD,
|
||||
redfishClient.BOOTSOURCE_PXE,
|
||||
}
|
||||
|
||||
m.On("GetSystem", ctx, systemID).
|
||||
Return(invalidSystem, nil, nil)
|
||||
|
||||
m.On("InsertVirtualMedia", ctx, "manager-1", "Cd", mock.Anything).
|
||||
Return(redfishClient.RedfishError{}, nil, nil)
|
||||
|
||||
rDCfg := getDefaultRedfishRemoteDirectObj(t, m)
|
||||
|
||||
err := rDCfg.DoRemoteDirect()
|
||||
|
||||
_, ok := err.(*RedfishClientError)
|
||||
assert.True(t, ok)
|
||||
}
|
||||
|
||||
func TestRedfishRemoteDirectSetSystemBootSourceFailed(t *testing.T) {
|
||||
|
||||
m := &redfishMocks.RedfishAPI{}
|
||||
defer m.AssertExpectations(t)
|
||||
|
||||
systemID := computerSystemID
|
||||
m.On("GetSystem", ctx, systemID).
|
||||
Return(SampleSystem, nil, nil)
|
||||
|
||||
m.On("InsertVirtualMedia", ctx, "manager-1", "Cd", mock.Anything).
|
||||
Return(redfishClient.RedfishError{}, nil, nil)
|
||||
|
||||
realErr := fmt.Errorf("Unauthorized")
|
||||
httpResp := &http.Response{
|
||||
StatusCode: 401,
|
||||
}
|
||||
m.On("SetSystem", ctx, systemID, mock.Anything).
|
||||
Times(1).
|
||||
Return(redfishClient.ComputerSystem{}, httpResp, realErr)
|
||||
|
||||
rDCfg := getDefaultRedfishRemoteDirectObj(t, m)
|
||||
|
||||
err := rDCfg.DoRemoteDirect()
|
||||
|
||||
_, ok := err.(*RedfishClientError)
|
||||
assert.True(t, ok)
|
||||
}
|
||||
|
||||
func TestRedfishRemoteDirectSystemRebootFailed(t *testing.T) {
|
||||
|
||||
m := &redfishMocks.RedfishAPI{}
|
||||
defer m.AssertExpectations(t)
|
||||
|
||||
systemID := computerSystemID
|
||||
|
||||
m.On("GetSystem", ctx, systemID).
|
||||
Return(SampleSystem, nil, nil)
|
||||
|
||||
m.On("InsertVirtualMedia", ctx, mock.Anything, mock.Anything, mock.Anything).
|
||||
Return(redfishClient.RedfishError{}, nil, nil)
|
||||
|
||||
m.On("SetSystem", ctx, systemID, mock.Anything).
|
||||
Times(1).
|
||||
Return(redfishClient.ComputerSystem{}, nil, nil)
|
||||
|
||||
realErr := fmt.Errorf("Unauthorized")
|
||||
httpResp := &http.Response{
|
||||
StatusCode: 401,
|
||||
}
|
||||
resetReq := redfishClient.ResetRequestBody{}
|
||||
resetReq.ResetType = redfishClient.RESETTYPE_FORCE_OFF
|
||||
m.On("ResetSystem", ctx, systemID, resetReq).
|
||||
Times(1).
|
||||
Return(redfishClient.RedfishError{}, httpResp, realErr)
|
||||
|
||||
rDCfg := getDefaultRedfishRemoteDirectObj(t, m)
|
||||
|
||||
err := rDCfg.DoRemoteDirect()
|
||||
|
||||
_, ok := err.(*RedfishClientError)
|
||||
assert.True(t, ok)
|
||||
}
|
118
pkg/remote/redfish/utils.go
Normal file
118
pkg/remote/redfish/utils.go
Normal file
@ -0,0 +1,118 @@
|
||||
package redfish
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
redfishApi "github.com/Nordix/go-redfish/api"
|
||||
redfishClient "github.com/Nordix/go-redfish/client"
|
||||
)
|
||||
|
||||
const (
|
||||
SystemRebootDelay = 2 * time.Second
|
||||
)
|
||||
|
||||
// Redfish Id ref is a URI which contains resource Id
|
||||
// as the last part. This function extracts resource
|
||||
// ID from ID ref
|
||||
func GetResourceIDFromURL(refURL string) (string, error) {
|
||||
|
||||
u, err := url.Parse(refURL)
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
url := strings.TrimSuffix(u.Path, "/")
|
||||
elems := strings.Split(url, "/")
|
||||
|
||||
id := elems[len(elems)-1]
|
||||
return id, nil
|
||||
}
|
||||
|
||||
// Checks whether an ID exists in Redfish IDref collection
|
||||
func IsIDInList(idRefList []redfishClient.IdRef, id string) bool {
|
||||
for _, r := range idRefList {
|
||||
rId, _ := GetResourceIDFromURL(r.OdataId)
|
||||
if rId == id {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// This function walks through the list of manager's virtual media resources
|
||||
// and gets the ID of virtualmedia which has type "CD" or "DVD"
|
||||
func GetVirtualMediaId(ctx context.Context,
|
||||
api redfishApi.RedfishAPI,
|
||||
managerId string,
|
||||
) (string, string, error) {
|
||||
|
||||
// TODO: Sushy emulator has a bug which sends 'virtualMedia.inserted' field as
|
||||
// string instead of a boolean which causes the redfish client to fail
|
||||
// while unmarshalling this field.
|
||||
// Insert logic here after the bug is fixed in sushy-emulator.
|
||||
return "Cd", "CD", nil
|
||||
}
|
||||
|
||||
// This function walks through the bootsources of a system and sets the bootsource
|
||||
// which is compatible with the given media type.
|
||||
func SetSystemBootSourceForMediaType(ctx context.Context,
|
||||
api redfishApi.RedfishAPI,
|
||||
systemId string,
|
||||
mediaType string) error {
|
||||
|
||||
/* Check available boot sources for system */
|
||||
system, _, err := api.GetSystem(ctx, systemId)
|
||||
if err != nil {
|
||||
return NewRedfishClientErrorf("Get System[%s] failed with err: %s", systemId, err.Error())
|
||||
}
|
||||
|
||||
allowableValues := system.Boot.BootSourceOverrideTargetRedfishAllowableValues
|
||||
for _, bootSource := range allowableValues {
|
||||
if strings.EqualFold(string(bootSource), mediaType) {
|
||||
/* set boot source */
|
||||
systemReq := redfishClient.ComputerSystem{}
|
||||
systemReq.Boot.BootSourceOverrideTarget = bootSource
|
||||
_, httpResp, err := api.SetSystem(ctx, systemId, systemReq)
|
||||
return ScreenRedfishError(httpResp, err)
|
||||
}
|
||||
}
|
||||
|
||||
return NewRedfishClientErrorf("failed to set system[%s] boot source", systemId)
|
||||
}
|
||||
|
||||
// Reboots a system by force shutoff and turning on.
|
||||
func RebootSystem(ctx context.Context, api redfishApi.RedfishAPI, systemId string) error {
|
||||
|
||||
resetReq := redfishClient.ResetRequestBody{}
|
||||
resetReq.ResetType = redfishClient.RESETTYPE_FORCE_OFF
|
||||
_, httpResp, err := api.ResetSystem(ctx, systemId, resetReq)
|
||||
if err != nil {
|
||||
return ScreenRedfishError(httpResp, err)
|
||||
}
|
||||
|
||||
time.Sleep(SystemRebootDelay)
|
||||
|
||||
resetReq.ResetType = redfishClient.RESETTYPE_ON
|
||||
_, httpResp, err = api.ResetSystem(ctx, systemId, resetReq)
|
||||
|
||||
return ScreenRedfishError(httpResp, err)
|
||||
}
|
||||
|
||||
// Insert the remote virtual media to the given virtual media id.
|
||||
// This assumes that isoPath is accessible to the redfish server and
|
||||
// virtualMedia device is either of type CD or DVD.
|
||||
func SetVirtualMedia(ctx context.Context,
|
||||
api redfishApi.RedfishAPI,
|
||||
managerId string,
|
||||
vMediaId string,
|
||||
isoPath string) error {
|
||||
|
||||
vMediaReq := redfishClient.InsertMediaRequestBody{}
|
||||
vMediaReq.Image = isoPath
|
||||
vMediaReq.Inserted = true
|
||||
_, httpResp, err := api.InsertVirtualMedia(ctx, managerId, vMediaId, vMediaReq)
|
||||
return ScreenRedfishError(httpResp, err)
|
||||
}
|
194
pkg/remote/redfish/utils_test.go
Normal file
194
pkg/remote/redfish/utils_test.go
Normal file
@ -0,0 +1,194 @@
|
||||
package redfish
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
redfishMocks "github.com/Nordix/go-redfish/api/mocks"
|
||||
redfishClient "github.com/Nordix/go-redfish/client"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
const (
|
||||
systemID = "123"
|
||||
)
|
||||
|
||||
func TestRedfishErrorNoError(t *testing.T) {
|
||||
|
||||
err := ScreenRedfishError(nil, nil)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestRedfishErrorNonNilErrorWithoutHttpResp(t *testing.T) {
|
||||
|
||||
realErr := fmt.Errorf("Sample error")
|
||||
err := ScreenRedfishError(nil, realErr)
|
||||
assert.Error(t, err)
|
||||
_, ok := err.(*RedfishClientError)
|
||||
assert.True(t, ok)
|
||||
}
|
||||
|
||||
func TestRedfishErrorNonNilErrorWithHttpRespError(t *testing.T) {
|
||||
|
||||
realErr := fmt.Errorf("Sample error")
|
||||
|
||||
httpResp := &http.Response{StatusCode: 408}
|
||||
err := ScreenRedfishError(httpResp, realErr)
|
||||
assert.Equal(t, err, NewRedfishClientErrorf(realErr.Error()))
|
||||
|
||||
httpResp.StatusCode = 400
|
||||
err = ScreenRedfishError(httpResp, realErr)
|
||||
assert.Equal(t, err, NewRedfishClientErrorf(realErr.Error()))
|
||||
|
||||
httpResp.StatusCode = 199
|
||||
err = ScreenRedfishError(httpResp, realErr)
|
||||
assert.Equal(t, err, NewRedfishClientErrorf(realErr.Error()))
|
||||
}
|
||||
|
||||
func TestRedfishErrorNonNilErrorWithHttpRespOK(t *testing.T) {
|
||||
|
||||
realErr := fmt.Errorf("Sample error")
|
||||
|
||||
httpResp := &http.Response{StatusCode: 204}
|
||||
err := ScreenRedfishError(httpResp, realErr)
|
||||
assert.NoError(t, err)
|
||||
|
||||
httpResp.StatusCode = 200
|
||||
err = ScreenRedfishError(httpResp, realErr)
|
||||
assert.NoError(t, err)
|
||||
|
||||
httpResp.StatusCode = 399
|
||||
err = ScreenRedfishError(httpResp, realErr)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestRedfishUtilGetResIDFromURL(t *testing.T) {
|
||||
|
||||
// simple case
|
||||
url := "api/user/123"
|
||||
id, err := GetResourceIDFromURL(url)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, id, "123")
|
||||
|
||||
// FQDN
|
||||
url = "http://www.abc.com/api/user/123"
|
||||
id, err = GetResourceIDFromURL(url)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, id, "123")
|
||||
|
||||
//Trailing slash
|
||||
url = "api/user/123/"
|
||||
id, err = GetResourceIDFromURL(url)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, id, "123")
|
||||
}
|
||||
|
||||
func TestRedfishUtilIsIdInList(t *testing.T) {
|
||||
|
||||
idList := []redfishClient.IdRef{
|
||||
{OdataId: "/path/to/id/1"},
|
||||
{OdataId: "/path/to/id/2"},
|
||||
{OdataId: "/path/to/id/3"},
|
||||
{OdataId: "/path/to/id/4"},
|
||||
}
|
||||
emptyList := []redfishClient.IdRef{}
|
||||
|
||||
res := IsIDInList(idList, "1")
|
||||
assert.True(t, res)
|
||||
|
||||
res = IsIDInList(idList, "100")
|
||||
assert.False(t, res)
|
||||
|
||||
res = IsIDInList(emptyList, "1")
|
||||
assert.False(t, res)
|
||||
}
|
||||
|
||||
func TestRedfishUtilRebootSystemOK(t *testing.T) {
|
||||
|
||||
m := &redfishMocks.RedfishAPI{}
|
||||
defer m.AssertExpectations(t)
|
||||
|
||||
ctx := context.Background()
|
||||
resetReq := redfishClient.ResetRequestBody{}
|
||||
resetReq.ResetType = redfishClient.RESETTYPE_FORCE_OFF
|
||||
m.On("ResetSystem", ctx, systemID, resetReq).
|
||||
Times(1).
|
||||
Return(redfishClient.RedfishError{}, nil, nil)
|
||||
|
||||
resetReq.ResetType = redfishClient.RESETTYPE_ON
|
||||
m.On("ResetSystem", ctx, systemID, resetReq).
|
||||
Times(1).
|
||||
Return(redfishClient.RedfishError{}, nil, nil)
|
||||
|
||||
err := RebootSystem(ctx, m, systemID)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestRedfishUtilRebootSystemForceOffError2(t *testing.T) {
|
||||
|
||||
m := &redfishMocks.RedfishAPI{}
|
||||
defer m.AssertExpectations(t)
|
||||
|
||||
ctx := context.Background()
|
||||
realErr := fmt.Errorf("Unauthorized")
|
||||
httpResp := &http.Response{
|
||||
StatusCode: 401,
|
||||
}
|
||||
resetReq := redfishClient.ResetRequestBody{}
|
||||
resetReq.ResetType = redfishClient.RESETTYPE_FORCE_OFF
|
||||
|
||||
m.On("ResetSystem", ctx, systemID, resetReq).
|
||||
Times(1).
|
||||
Return(redfishClient.RedfishError{}, httpResp, realErr)
|
||||
|
||||
err := RebootSystem(ctx, m, systemID)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestRedfishUtilRebootSystemForceOffError(t *testing.T) {
|
||||
|
||||
m := &redfishMocks.RedfishAPI{}
|
||||
defer m.AssertExpectations(t)
|
||||
|
||||
ctx := context.Background()
|
||||
realErr := fmt.Errorf("Unauthorized")
|
||||
httpResp := &http.Response{
|
||||
StatusCode: 401,
|
||||
}
|
||||
resetReq := redfishClient.ResetRequestBody{}
|
||||
resetReq.ResetType = redfishClient.RESETTYPE_FORCE_OFF
|
||||
m.On("ResetSystem", ctx, systemID, resetReq).
|
||||
Times(1).
|
||||
Return(redfishClient.RedfishError{}, httpResp, realErr)
|
||||
|
||||
err := RebootSystem(ctx, m, systemID)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestRedfishUtilRebootSystemTurningOnError(t *testing.T) {
|
||||
|
||||
m := &redfishMocks.RedfishAPI{}
|
||||
defer m.AssertExpectations(t)
|
||||
|
||||
ctx := context.Background()
|
||||
resetReq := redfishClient.ResetRequestBody{}
|
||||
resetReq.ResetType = redfishClient.RESETTYPE_FORCE_OFF
|
||||
m.On("ResetSystem", ctx, systemID, resetReq).
|
||||
Times(1).
|
||||
Return(redfishClient.RedfishError{}, nil, nil)
|
||||
|
||||
realErr := fmt.Errorf("Unauthorized")
|
||||
httpResp := &http.Response{
|
||||
StatusCode: 401,
|
||||
}
|
||||
resetOnReq := redfishClient.ResetRequestBody{}
|
||||
resetOnReq.ResetType = redfishClient.RESETTYPE_ON
|
||||
m.On("ResetSystem", ctx, systemID, resetOnReq).
|
||||
Times(1).
|
||||
Return(redfishClient.RedfishError{}, httpResp, realErr)
|
||||
|
||||
err := RebootSystem(ctx, m, systemID)
|
||||
assert.Error(t, err)
|
||||
}
|
86
pkg/remote/remote_direct.go
Normal file
86
pkg/remote/remote_direct.go
Normal file
@ -0,0 +1,86 @@
|
||||
package remote
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
alog "opendev.org/airship/airshipctl/pkg/log"
|
||||
redfish "opendev.org/airship/airshipctl/pkg/remote/redfish"
|
||||
)
|
||||
|
||||
const (
|
||||
AirshipRemoteTypeRedfish string = "redfish"
|
||||
AirshipRemoteTypeSmash string = "smash"
|
||||
)
|
||||
|
||||
// This structure defines the common remote direct config
|
||||
// for all remote types.
|
||||
type RemoteDirectConfig struct {
|
||||
// remote type
|
||||
RemoteType string
|
||||
|
||||
// remote URL
|
||||
RemoteURL string
|
||||
|
||||
// ephemeral Host ID
|
||||
EphemeralNodeId string
|
||||
|
||||
// ISO URL
|
||||
IsoPath string
|
||||
|
||||
// TODO: Ephemeral Node IP
|
||||
|
||||
// TODO: kubeconfig (in object form or raw yaml?) for ephemeral node validation.
|
||||
|
||||
// TODO: More fields can be added on need basis
|
||||
}
|
||||
|
||||
// Interface to be implemented by remoteDirect implementation
|
||||
type RemoteDirectClient interface {
|
||||
DoRemoteDirect() error
|
||||
}
|
||||
|
||||
// Get remotedirect client based on config
|
||||
func getRemoteDirectClient(remoteConfig RemoteDirectConfig) (RemoteDirectClient, error) {
|
||||
|
||||
var client RemoteDirectClient
|
||||
var err error
|
||||
|
||||
switch remoteConfig.RemoteType {
|
||||
case AirshipRemoteTypeRedfish:
|
||||
alog.Debug("Remote type redfish")
|
||||
|
||||
client, err = redfish.NewRedfishRemoteDirectClient(
|
||||
context.Background(),
|
||||
remoteConfig.RemoteURL,
|
||||
remoteConfig.EphemeralNodeId,
|
||||
remoteConfig.IsoPath)
|
||||
if err != nil {
|
||||
alog.Debugf("redfish remotedirect client creation failed")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
default:
|
||||
return nil, NewRemoteDirectErrorf("invalid remote type")
|
||||
}
|
||||
|
||||
return client, nil
|
||||
}
|
||||
|
||||
// Top level function to execute remote direct based on remote type
|
||||
func DoRemoteDirect(remoteConfig RemoteDirectConfig) error {
|
||||
|
||||
client, err := getRemoteDirectClient(remoteConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = client.DoRemoteDirect()
|
||||
if err != nil {
|
||||
alog.Debugf("remote direct failed: %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
alog.Print("Remote direct successfully completed")
|
||||
|
||||
return nil
|
||||
}
|
84
pkg/remote/remote_direct_test.go
Normal file
84
pkg/remote/remote_direct_test.go
Normal file
@ -0,0 +1,84 @@
|
||||
package remote
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
redfish "opendev.org/airship/airshipctl/pkg/remote/redfish"
|
||||
)
|
||||
|
||||
func TestUnknownRemoteType(t *testing.T) {
|
||||
|
||||
rdCfg := RemoteDirectConfig{
|
||||
RemoteType: "new-remote",
|
||||
RemoteURL: "http://localhost:8000",
|
||||
EphemeralNodeId: "test-node",
|
||||
IsoPath: "/test.iso",
|
||||
}
|
||||
|
||||
err := DoRemoteDirect(rdCfg)
|
||||
|
||||
_, ok := err.(*RemoteDirectError)
|
||||
assert.True(t, ok)
|
||||
}
|
||||
|
||||
func TestRedfishRemoteDirectWithBogusConfig(t *testing.T) {
|
||||
|
||||
rdCfg := RemoteDirectConfig{
|
||||
RemoteType: "redfish",
|
||||
RemoteURL: "http://nolocalhost:8888",
|
||||
EphemeralNodeId: "test-node",
|
||||
IsoPath: "/test.iso",
|
||||
}
|
||||
|
||||
err := DoRemoteDirect(rdCfg)
|
||||
|
||||
_, ok := err.(*redfish.RedfishClientError)
|
||||
assert.True(t, ok)
|
||||
}
|
||||
|
||||
func TestRedfishRemoteDirectWithEmptyURL(t *testing.T) {
|
||||
|
||||
rdCfg := RemoteDirectConfig{
|
||||
RemoteType: "redfish",
|
||||
RemoteURL: "",
|
||||
EphemeralNodeId: "test-node",
|
||||
IsoPath: "/test.iso",
|
||||
}
|
||||
|
||||
err := DoRemoteDirect(rdCfg)
|
||||
|
||||
_, ok := err.(*redfish.RedfishConfigError)
|
||||
assert.True(t, ok)
|
||||
}
|
||||
|
||||
func TestRedfishRemoteDirectWithEmptyNodeID(t *testing.T) {
|
||||
|
||||
rdCfg := RemoteDirectConfig{
|
||||
RemoteType: "redfish",
|
||||
RemoteURL: "http://nolocalhost:8888",
|
||||
EphemeralNodeId: "",
|
||||
IsoPath: "/test.iso",
|
||||
}
|
||||
|
||||
err := DoRemoteDirect(rdCfg)
|
||||
|
||||
_, ok := err.(*redfish.RedfishConfigError)
|
||||
assert.True(t, ok)
|
||||
}
|
||||
|
||||
func TestRedfishRemoteDirectWithEmptyIsoPath(t *testing.T) {
|
||||
|
||||
rdCfg := RemoteDirectConfig{
|
||||
RemoteType: "redfish",
|
||||
RemoteURL: "http://nolocalhost:8888",
|
||||
EphemeralNodeId: "123",
|
||||
IsoPath: "",
|
||||
}
|
||||
|
||||
err := DoRemoteDirect(rdCfg)
|
||||
|
||||
_, ok := err.(*redfish.RedfishConfigError)
|
||||
assert.True(t, ok)
|
||||
}
|
Loading…
Reference in New Issue
Block a user