1package baremetal 2 3import ( 4 "time" 5 6 "github.com/scaleway/scaleway-sdk-go/internal/async" 7 "github.com/scaleway/scaleway-sdk-go/internal/errors" 8 "github.com/scaleway/scaleway-sdk-go/scw" 9) 10 11const ( 12 defaultRetryInterval = 15 * time.Second 13 defaultTimeout = 2 * time.Hour 14) 15 16// WaitForServerRequest is used by WaitForServer method. 17type WaitForServerRequest struct { 18 ServerID string 19 Zone scw.Zone 20 Timeout *time.Duration 21 RetryInterval *time.Duration 22} 23 24// WaitForServer wait for the server to be in a "terminal state" before returning. 25// This function can be used to wait for a server to be created. 26func (s *API) WaitForServer(req *WaitForServerRequest, opts ...scw.RequestOption) (*Server, error) { 27 timeout := defaultTimeout 28 if req.Timeout != nil { 29 timeout = *req.Timeout 30 } 31 retryInterval := defaultRetryInterval 32 if req.RetryInterval != nil { 33 retryInterval = *req.RetryInterval 34 } 35 36 terminalStatus := map[ServerStatus]struct{}{ 37 ServerStatusReady: {}, 38 ServerStatusStopped: {}, 39 ServerStatusError: {}, 40 ServerStatusLocked: {}, 41 ServerStatusUnknown: {}, 42 } 43 44 server, err := async.WaitSync(&async.WaitSyncConfig{ 45 Get: func() (interface{}, bool, error) { 46 res, err := s.GetServer(&GetServerRequest{ 47 ServerID: req.ServerID, 48 Zone: req.Zone, 49 }, opts...) 50 if err != nil { 51 return nil, false, err 52 } 53 54 _, isTerminal := terminalStatus[res.Status] 55 return res, isTerminal, err 56 }, 57 Timeout: timeout, 58 IntervalStrategy: async.LinearIntervalStrategy(retryInterval), 59 }) 60 if err != nil { 61 return nil, errors.Wrap(err, "waiting for server failed") 62 } 63 64 return server.(*Server), nil 65} 66 67// WaitForServerInstallRequest is used by WaitForServerInstall method. 68type WaitForServerInstallRequest struct { 69 ServerID string 70 Zone scw.Zone 71 Timeout *time.Duration 72 RetryInterval *time.Duration 73} 74 75// WaitForServerInstall wait for the server install to be in a 76// "terminal state" before returning. 77// This function can be used to wait for a server to be installed. 78func (s *API) WaitForServerInstall(req *WaitForServerInstallRequest, opts ...scw.RequestOption) (*Server, error) { 79 timeout := defaultTimeout 80 if req.Timeout != nil { 81 timeout = *req.Timeout 82 } 83 retryInterval := defaultRetryInterval 84 if req.RetryInterval != nil { 85 retryInterval = *req.RetryInterval 86 } 87 88 installTerminalStatus := map[ServerInstallStatus]struct{}{ 89 ServerInstallStatusCompleted: {}, 90 ServerInstallStatusError: {}, 91 ServerInstallStatusUnknown: {}, 92 } 93 94 server, err := async.WaitSync(&async.WaitSyncConfig{ 95 Get: func() (interface{}, bool, error) { 96 res, err := s.GetServer(&GetServerRequest{ 97 ServerID: req.ServerID, 98 Zone: req.Zone, 99 }, opts...) 100 if err != nil { 101 return nil, false, err 102 } 103 104 if res.Install == nil { 105 return nil, false, errors.New("server creation has not begun for server %s", req.ServerID) 106 } 107 108 _, isTerminal := installTerminalStatus[res.Install.Status] 109 return res, isTerminal, err 110 }, 111 Timeout: timeout, 112 IntervalStrategy: async.LinearIntervalStrategy(retryInterval), 113 }) 114 if err != nil { 115 return nil, errors.Wrap(err, "waiting for server installation failed") 116 } 117 118 return server.(*Server), nil 119} 120 121// GetServerOffer returns the offer of a baremetal server 122func (s *API) GetServerOffer(server *Server) (*Offer, error) { 123 offer, err := s.GetOffer(&GetOfferRequest{ 124 OfferID: server.OfferID, 125 Zone: server.Zone, 126 }) 127 if err != nil { 128 return nil, err 129 } 130 131 return offer, nil 132} 133 134type GetOfferByNameRequest struct { 135 OfferName string 136 Zone scw.Zone 137} 138 139// GetOfferByName returns an offer from its commercial name 140func (s *API) GetOfferByName(req *GetOfferByNameRequest) (*Offer, error) { 141 res, err := s.ListOffers(&ListOffersRequest{ 142 Zone: req.Zone, 143 }, scw.WithAllPages()) 144 if err != nil { 145 return nil, err 146 } 147 148 for _, offer := range res.Offers { 149 if req.OfferName == offer.Name { 150 return offer, nil 151 } 152 } 153 154 return nil, errors.New("could not find the offer ID from name %s", req.OfferName) 155} 156