diff --git a/modules/test/apis/common.go b/modules/test/apis/common.go index 494ed537..5c88455f 100644 --- a/modules/test/apis/common.go +++ b/modules/test/apis/common.go @@ -33,37 +33,42 @@ type Handler struct { // APIFixture is a base struct to implement OpenStack API simulators for the // EnvTest. type APIFixture struct { - log logr.Logger - server *FakeAPIServer - ownsServer bool - urlBase string + Log logr.Logger + Server *FakeAPIServer + OwnsServer bool + URLBase string } -func (f *APIFixture) logRequest(r *http.Request) { - f.log.Info("OpenStack API request", "method", r.Method, "URI", r.RequestURI) +// LogRequest logs details of the http.Request +func (f *APIFixture) LogRequest(r *http.Request) { + f.Log.Info("OpenStack API request", "method", r.Method, "URI", r.RequestURI) } // Cleanup stops the embedded http server if it was created by the fixture // during setup func (f *APIFixture) Cleanup() { - if f.ownsServer { - f.server.Cleanup() + if f.OwnsServer { + f.Server.Cleanup() } } // Endpoint is the URL the fixture's embedded http server listening on func (f *APIFixture) Endpoint() string { - return f.server.Endpoint() + f.urlBase + return f.Server.Endpoint() + f.URLBase } -func (f *APIFixture) unexpectedRequest(w http.ResponseWriter, r *http.Request) { - f.log.Info("Unexpected OpenStackAPI request", "method", r.Method, "URI", r.RequestURI) +// UnexpectedRequest sends a HTTP 500 response. Use it if the request is +// understood but not implemented by the fixture +func (f *APIFixture) UnexpectedRequest(w http.ResponseWriter, r *http.Request) { + f.Log.Info("Unexpected OpenStackAPI request", "method", r.Method, "URI", r.RequestURI) w.WriteHeader(500) fmt.Fprintf(w, "Unexpected OpenStackAPI request %s %s", r.Method, r.RequestURI) } -func (f *APIFixture) internalError(err error, msg string, w http.ResponseWriter, r *http.Request) { - f.log.Info("Internal error", "method", r.Method, "URI", r.RequestURI, "error", err, "message", msg) +// InternalError sends a HTTP 500 response Use it if there was an unexpected +// error during the request processing +func (f *APIFixture) InternalError(err error, msg string, w http.ResponseWriter, r *http.Request) { + f.Log.Info("Internal error", "method", r.Method, "URI", r.RequestURI, "error", err, "message", msg) w.WriteHeader(500) fmt.Fprintf(w, "Internal error in %s %s: %s: %v", r.Method, r.RequestURI, msg, err) } diff --git a/modules/test/apis/keystone.go b/modules/test/apis/keystone.go index 94af1f1d..e21e3d45 100644 --- a/modules/test/apis/keystone.go +++ b/modules/test/apis/keystone.go @@ -68,7 +68,7 @@ func NewKeystoneAPIFixtureWithServer(log logr.Logger) *KeystoneAPIFixture { server := &FakeAPIServer{} server.Setup(log) fixture := AddKeystoneAPIFixture(log, server) - fixture.ownsServer = true + fixture.OwnsServer = true return fixture } @@ -78,10 +78,10 @@ func NewKeystoneAPIFixtureWithServer(log logr.Logger) *KeystoneAPIFixture { func AddKeystoneAPIFixture(log logr.Logger, server *FakeAPIServer) *KeystoneAPIFixture { fixture := &KeystoneAPIFixture{ APIFixture: APIFixture{ - server: server, - log: log, - urlBase: "/identity", - ownsServer: false, + Server: server, + Log: log, + URLBase: "/identity", + OwnsServer: false, }, Users: map[string]users.User{}, Domains: map[string]domains.Domain{}, @@ -111,16 +111,16 @@ func (f *KeystoneAPIFixture) registerNormalHandlers() { } func (f *KeystoneAPIFixture) registerHandler(handler Handler) { - f.server.mux.HandleFunc(f.urlBase+handler.Pattern, handler.Func) + f.Server.AddHandler(f.URLBase+handler.Pattern, handler.Func) } // HandleVersion responds with a valid keystone version response func (f *KeystoneAPIFixture) HandleVersion(w http.ResponseWriter, r *http.Request) { - f.logRequest(r) + f.LogRequest(r) // The /identity URL matches to every request if no handle registered with a more // specific URL pattern - if r.RequestURI != f.urlBase+"/" { - f.unexpectedRequest(w, r) + if r.RequestURI != f.URLBase+"/" { + f.UnexpectedRequest(w, r) return } @@ -149,14 +149,14 @@ func (f *KeystoneAPIFixture) HandleVersion(w http.ResponseWriter, r *http.Reques } `, f.Endpoint()) default: - f.unexpectedRequest(w, r) + f.UnexpectedRequest(w, r) return } } // HandleToken responds with a valid keystone token func (f *KeystoneAPIFixture) HandleToken(w http.ResponseWriter, r *http.Request) { - f.logRequest(r) + f.LogRequest(r) switch r.Method { case "POST": w.Header().Add("Content-Type", "application/json") @@ -185,21 +185,21 @@ func (f *KeystoneAPIFixture) HandleToken(w http.ResponseWriter, r *http.Request) } `, f.Endpoint()) default: - f.unexpectedRequest(w, r) + f.UnexpectedRequest(w, r) return } } // HandleUsers handles the happy path of GET /v3/users and POST /v3/users API func (f *KeystoneAPIFixture) HandleUsers(w http.ResponseWriter, r *http.Request) { - f.logRequest(r) + f.LogRequest(r) switch r.Method { case "GET": f.GetUsers(w, r) case "POST": f.CreateUser(w, r) default: - f.unexpectedRequest(w, r) + f.UnexpectedRequest(w, r) return } } @@ -225,7 +225,7 @@ func (f *KeystoneAPIFixture) GetUsers(w http.ResponseWriter, r *http.Request) { bytes, err := json.Marshal(&s) if err != nil { - f.internalError(err, "Error during marshalling response", w, r) + f.InternalError(err, "Error during marshalling response", w, r) return } w.Header().Add("Content-Type", "application/json") @@ -237,7 +237,7 @@ func (f *KeystoneAPIFixture) GetUsers(w http.ResponseWriter, r *http.Request) { func (f *KeystoneAPIFixture) CreateUser(w http.ResponseWriter, r *http.Request) { bytes, err := io.ReadAll(r.Body) if err != nil { - f.internalError(err, "Error reading request body", w, r) + f.InternalError(err, "Error reading request body", w, r) return } var s struct { @@ -245,7 +245,7 @@ func (f *KeystoneAPIFixture) CreateUser(w http.ResponseWriter, r *http.Request) } err = json.Unmarshal(bytes, &s) if err != nil { - f.internalError(err, "Error during unmarshalling request", w, r) + f.InternalError(err, "Error during unmarshalling request", w, r) return } if s.User.ID == "" { @@ -256,7 +256,7 @@ func (f *KeystoneAPIFixture) CreateUser(w http.ResponseWriter, r *http.Request) bytes, err = json.Marshal(&s) if err != nil { - f.internalError(err, "Error during marshalling response", w, r) + f.InternalError(err, "Error during marshalling response", w, r) return } w.Header().Add("Content-Type", "application/json") @@ -266,14 +266,14 @@ func (f *KeystoneAPIFixture) CreateUser(w http.ResponseWriter, r *http.Request) // HandleDomains handles the happy path of GET /v3/domains and POST /v3/domains API func (f *KeystoneAPIFixture) HandleDomains(w http.ResponseWriter, r *http.Request) { - f.logRequest(r) + f.LogRequest(r) switch r.Method { case "GET": f.GetDomains(w, r) case "POST": f.CreateDomain(w, r) default: - f.unexpectedRequest(w, r) + f.UnexpectedRequest(w, r) return } } @@ -299,7 +299,7 @@ func (f *KeystoneAPIFixture) GetDomains(w http.ResponseWriter, r *http.Request) bytes, err := json.Marshal(&s) if err != nil { - f.internalError(err, "Error during marshalling response", w, r) + f.InternalError(err, "Error during marshalling response", w, r) return } w.Header().Add("Content-Type", "application/json") @@ -311,7 +311,7 @@ func (f *KeystoneAPIFixture) GetDomains(w http.ResponseWriter, r *http.Request) func (f *KeystoneAPIFixture) CreateDomain(w http.ResponseWriter, r *http.Request) { bytes, err := io.ReadAll(r.Body) if err != nil { - f.internalError(err, "Error reading request body", w, r) + f.InternalError(err, "Error reading request body", w, r) return } var s struct { @@ -319,7 +319,7 @@ func (f *KeystoneAPIFixture) CreateDomain(w http.ResponseWriter, r *http.Request } err = json.Unmarshal(bytes, &s) if err != nil { - f.internalError(err, "Error during unmarshalling request", w, r) + f.InternalError(err, "Error during unmarshalling request", w, r) return } if s.Domain.ID == "" { @@ -330,7 +330,7 @@ func (f *KeystoneAPIFixture) CreateDomain(w http.ResponseWriter, r *http.Request bytes, err = json.Marshal(&s) if err != nil { - f.internalError(err, "Error during marshalling response", w, r) + f.InternalError(err, "Error during marshalling response", w, r) return } w.Header().Add("Content-Type", "application/json") diff --git a/modules/test/apis/server.go b/modules/test/apis/server.go index 37dfcbb3..22e7da07 100644 --- a/modules/test/apis/server.go +++ b/modules/test/apis/server.go @@ -43,6 +43,12 @@ func (s *FakeAPIServer) Setup(log logr.Logger) { s.mux.HandleFunc("/", s.fallbackHandler) } +// AddHandlers adds a function to be called if a request is received for the URL +// matching the pattern +func (s *FakeAPIServer) AddHandler(pattern string, handler func(http.ResponseWriter, *http.Request)) { + s.mux.HandleFunc(pattern, handler) +} + func (s *FakeAPIServer) fallbackHandler(w http.ResponseWriter, r *http.Request) { if r == nil { s.log.Info("Unexpected OpenStackAPI nil request")