diff --git a/go.mod b/go.mod
index 0ad87091c..099f43ff8 100644
--- a/go.mod
+++ b/go.mod
@@ -20,7 +20,7 @@ require (
github.com/google/uuid v1.1.1
github.com/gophercloud/gophercloud v0.11.0
github.com/julienschmidt/httprouter v1.2.0
- github.com/kolo/xmlrpc v0.0.0-20190417161013-de6d879202d7
+ github.com/kolo/xmlrpc v0.0.0-20200310150728-e0350524596b
github.com/labstack/echo/v4 v4.1.11
github.com/pkg/errors v0.9.1 // indirect
github.com/stretchr/testify v1.5.1
diff --git a/go.sum b/go.sum
index 1dbf11c1b..cbc3e81b4 100644
--- a/go.sum
+++ b/go.sum
@@ -74,8 +74,8 @@ github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5i
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/julienschmidt/httprouter v1.2.0 h1:TDTW5Yz1mjftljbcKqRcrYhd4XeOoI98t+9HbQbYf7g=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
-github.com/kolo/xmlrpc v0.0.0-20190417161013-de6d879202d7 h1:kL2yi3DjwkRWFgKwD5COyl4XMLKhfOvqck4xyis7EIw=
-github.com/kolo/xmlrpc v0.0.0-20190417161013-de6d879202d7/go.mod h1:o03bZfuBwAXHetKXuInt4S7omeXUu62/A845kiycsSQ=
+github.com/kolo/xmlrpc v0.0.0-20200310150728-e0350524596b h1:DzHy0GlWeF0KAglaTMY7Q+khIFoG8toHP+wLFBVBQJc=
+github.com/kolo/xmlrpc v0.0.0-20200310150728-e0350524596b/go.mod h1:o03bZfuBwAXHetKXuInt4S7omeXUu62/A845kiycsSQ=
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=
diff --git a/golang-github-osbuild-composer.spec b/golang-github-osbuild-composer.spec
index 3d771a1fd..eeec12f5d 100644
--- a/golang-github-osbuild-composer.spec
+++ b/golang-github-osbuild-composer.spec
@@ -64,6 +64,20 @@ Provides: weldr
%goprep
%endif
+%if 0%{?fedora} && 0%{?fedora} <= 32
+# Fedora 32 and older ships a different kolo/xmlrpc API. We cannot specify
+# build tags in gobuild macro because the macro itself specifies build tags.
+# and -tags argument cannot be used more than once.
+# Therefore, this ugly hack with build tags switcharoo is required.
+# Remove when F32 is EOL.
+
+# Remove the build constraint from the wrapper of the old API
+sed -i "s$// +build kolo_xmlrpc_oldapi$// +build !kolo_xmlrpc_oldapi$" internal/upload/koji/xmlrpc-response-oldapi.go
+
+# Add a build constraint to the wrapper of the new API
+sed -i "s$// +build !kolo_xmlrpc_oldapi$// +build kolo_xmlrpc_oldapi$" internal/upload/koji/xmlrpc-response.go
+%endif
+
%build
%if 0%{?rhel}
GO_BUILD_PATH=$PWD/_build
diff --git a/internal/upload/koji/xmlrpc-response-oldapi.go b/internal/upload/koji/xmlrpc-response-oldapi.go
index 24b4bc732..3b52a4372 100644
--- a/internal/upload/koji/xmlrpc-response-oldapi.go
+++ b/internal/upload/koji/xmlrpc-response-oldapi.go
@@ -1,4 +1,6 @@
-// This files provides a wrapper around kolo/xmlrpc response handling.
+// +build kolo_xmlrpc_oldapi
+//
+// This file provides a wrapper around kolo/xmlrpc response handling.
//
// Commit e3ad6d89 of the xmlrpc library changed the API of response handling.
// This means that different APIs are available in Fedora 32 and 33 (it does
diff --git a/internal/upload/koji/xmlrpc-response.go b/internal/upload/koji/xmlrpc-response.go
index e69de29bb..dc4f9be11 100644
--- a/internal/upload/koji/xmlrpc-response.go
+++ b/internal/upload/koji/xmlrpc-response.go
@@ -0,0 +1,34 @@
+// +build !kolo_xmlrpc_oldapi
+//
+// This file provides a wrapper around kolo/xmlrpc response handling.
+//
+// Commit e3ad6d89 of the xmlrpc library changed the API of response handling.
+// This means that different APIs are available in Fedora 32 and 33 (it does
+// not matter for RHEL as uses vendored libraries).
+// This wrapper allows us to use both xmlrpc's APIs using buildflags.
+//
+// This file is a wrapper for xmlrpc equal or newer than e3ad6d89.
+
+package koji
+
+import (
+ "fmt"
+
+ "github.com/kolo/xmlrpc"
+)
+
+// processXMLRPCResponse is a wrapper around kolo/xmlrpc
+func processXMLRPCResponse(body []byte, reply interface{}) error {
+ resp := xmlrpc.Response(body)
+
+ if resp.Err() != nil {
+ return fmt.Errorf("xmlrpc server returned an error: %v", resp.Err())
+ }
+
+ err := resp.Unmarshal(reply)
+ if err != nil {
+ return fmt.Errorf("cannot unmarshal the xmlrpc response: %v", err)
+ }
+
+ return nil
+}
diff --git a/osbuild-composer.spec b/osbuild-composer.spec
index cf9fb5533..e7d364d8f 100644
--- a/osbuild-composer.spec
+++ b/osbuild-composer.spec
@@ -87,6 +87,20 @@ Provides: golang-github-osbuild-composer = %{version}-%{release}
%goprep
%endif
+%if 0%{?fedora} && 0%{?fedora} <= 32
+# Fedora 32 and older ships a different kolo/xmlrpc API. We cannot specify
+# build tags in gobuild macro because the macro itself specifies build tags.
+# and -tags argument cannot be used more than once.
+# Therefore, this ugly hack with build tags switcharoo is required.
+# Remove when F32 is EOL.
+
+# Remove the build constraint from the wrapper of the old API
+sed -i "s$// +build kolo_xmlrpc_oldapi$// +build !kolo_xmlrpc_oldapi$" internal/upload/koji/xmlrpc-response-oldapi.go
+
+# Add a build constraint to the wrapper of the new API
+sed -i "s$// +build !kolo_xmlrpc_oldapi$// +build kolo_xmlrpc_oldapi$" internal/upload/koji/xmlrpc-response.go
+%endif
+
%build
%if 0%{?rhel}
GO_BUILD_PATH=$PWD/_build
diff --git a/vendor/github.com/kolo/xmlrpc/README.md b/vendor/github.com/kolo/xmlrpc/README.md
index 8113cfcc3..fecfcd839 100644
--- a/vendor/github.com/kolo/xmlrpc/README.md
+++ b/vendor/github.com/kolo/xmlrpc/README.md
@@ -44,11 +44,12 @@ Data types encoding rules:
* xmlrpc.Base64 encoded to base64;
* slice encoded to array;
-Structs decoded to struct by following rules:
+Structs encoded to struct by following rules:
* all public field become struct members;
* field name become member name;
* if field has xmlrpc tag, its value become member name.
+* for fields tagged with `",omitempty"`, empty values are omitted;
Server method can accept few arguments, to handle this case there is
special approach to handle slice of empty interfaces (`[]interface{}`).
diff --git a/vendor/github.com/kolo/xmlrpc/client.go b/vendor/github.com/kolo/xmlrpc/client.go
index 3aa86ce2c..643dc1c10 100644
--- a/vendor/github.com/kolo/xmlrpc/client.go
+++ b/vendor/github.com/kolo/xmlrpc/client.go
@@ -31,7 +31,7 @@ type clientCodec struct {
responses map[uint64]*http.Response
mutex sync.Mutex
- response *Response
+ response Response
// ready presents channel, that is used to link request and it`s response.
ready chan uint64
@@ -43,16 +43,16 @@ type clientCodec struct {
func (codec *clientCodec) WriteRequest(request *rpc.Request, args interface{}) (err error) {
httpRequest, err := NewRequest(codec.url.String(), request.ServiceMethod, args)
+ if err != nil {
+ return err
+ }
+
if codec.cookies != nil {
for _, cookie := range codec.cookies.Cookies(codec.url) {
httpRequest.AddCookie(cookie)
}
}
- if err != nil {
- return err
- }
-
var httpResponse *http.Response
httpResponse, err = codec.httpClient.Do(httpRequest)
@@ -75,43 +75,39 @@ func (codec *clientCodec) WriteRequest(request *rpc.Request, args interface{}) (
func (codec *clientCodec) ReadResponseHeader(response *rpc.Response) (err error) {
var seq uint64
-
select {
case seq = <-codec.ready:
case <-codec.close:
return errors.New("codec is closed")
}
-
- codec.mutex.Lock()
- httpResponse := codec.responses[seq]
- codec.mutex.Unlock()
-
- if httpResponse.StatusCode < 200 || httpResponse.StatusCode >= 300 {
- return fmt.Errorf("request error: bad status code - %d", httpResponse.StatusCode)
- }
-
- respData, err := ioutil.ReadAll(httpResponse.Body)
-
- if err != nil {
- return err
- }
-
- httpResponse.Body.Close()
-
- resp := NewResponse(respData)
-
- if resp.Failed() {
- response.Error = fmt.Sprintf("%v", resp.Err())
- }
-
- codec.response = resp
-
response.Seq = seq
codec.mutex.Lock()
+ httpResponse := codec.responses[seq]
delete(codec.responses, seq)
codec.mutex.Unlock()
+ defer httpResponse.Body.Close()
+
+ if httpResponse.StatusCode < 200 || httpResponse.StatusCode >= 300 {
+ response.Error = fmt.Sprintf("request error: bad status code - %d", httpResponse.StatusCode)
+ return nil
+ }
+
+ body, err := ioutil.ReadAll(httpResponse.Body)
+ if err != nil {
+ response.Error = err.Error()
+ return nil
+ }
+
+ resp := Response(body)
+ if err := resp.Err(); err != nil {
+ response.Error = err.Error()
+ return nil
+ }
+
+ codec.response = resp
+
return nil
}
@@ -119,12 +115,7 @@ func (codec *clientCodec) ReadResponseBody(v interface{}) (err error) {
if v == nil {
return nil
}
-
- if err = codec.response.Unmarshal(v); err != nil {
- return err
- }
-
- return nil
+ return codec.response.Unmarshal(v)
}
func (codec *clientCodec) Close() error {
diff --git a/vendor/github.com/kolo/xmlrpc/decoder.go b/vendor/github.com/kolo/xmlrpc/decoder.go
index 61712d8aa..d4dcb19ad 100644
--- a/vendor/github.com/kolo/xmlrpc/decoder.go
+++ b/vendor/github.com/kolo/xmlrpc/decoder.go
@@ -130,8 +130,9 @@ func (dec *decoder) decodeValue(val reflect.Value) error {
ismap = true
} else if checkType(val, reflect.Interface) == nil && val.IsNil() {
var dummy map[string]interface{}
- pmap = reflect.New(reflect.TypeOf(dummy)).Elem()
- valType = pmap.Type()
+ valType = reflect.TypeOf(dummy)
+ pmap = reflect.New(valType).Elem()
+ val.Set(pmap)
ismap = true
} else {
return err
diff --git a/vendor/github.com/kolo/xmlrpc/encoder.go b/vendor/github.com/kolo/xmlrpc/encoder.go
index d585a7d3f..7ab271aa5 100644
--- a/vendor/github.com/kolo/xmlrpc/encoder.go
+++ b/vendor/github.com/kolo/xmlrpc/encoder.go
@@ -7,9 +7,13 @@ import (
"reflect"
"sort"
"strconv"
+ "strings"
"time"
)
+// Base64 represents value in base64 encoding
+type Base64 string
+
type encodeFunc func(reflect.Value) ([]byte, error)
func marshal(v interface{}) ([]byte, error) {
@@ -80,28 +84,34 @@ func encodeValue(val reflect.Value) ([]byte, error) {
return []byte(fmt.Sprintf("%s", string(b))), nil
}
-func encodeStruct(val reflect.Value) ([]byte, error) {
+func encodeStruct(structVal reflect.Value) ([]byte, error) {
var b bytes.Buffer
b.WriteString("")
- t := val.Type()
- for i := 0; i < t.NumField(); i++ {
- b.WriteString("")
- f := t.Field(i)
+ structType := structVal.Type()
+ for i := 0; i < structType.NumField(); i++ {
+ fieldVal := structVal.Field(i)
+ fieldType := structType.Field(i)
- name := f.Tag.Get("xmlrpc")
- if name == "" {
- name = f.Name
+ name := fieldType.Tag.Get("xmlrpc")
+ // if the tag has the omitempty property, skip it
+ if strings.HasSuffix(name, ",omitempty") && isZero(fieldVal) {
+ continue
+ }
+ name = strings.TrimSuffix(name, ",omitempty")
+ if name == "" {
+ name = fieldType.Name
}
- b.WriteString(fmt.Sprintf("%s", name))
- p, err := encodeValue(val.FieldByName(f.Name))
+ p, err := encodeValue(fieldVal)
if err != nil {
return nil, err
}
- b.Write(p)
+ b.WriteString("")
+ b.WriteString(fmt.Sprintf("%s", name))
+ b.Write(p)
b.WriteString("")
}
diff --git a/vendor/github.com/kolo/xmlrpc/is_zero.go b/vendor/github.com/kolo/xmlrpc/is_zero.go
new file mode 100644
index 000000000..65276d04a
--- /dev/null
+++ b/vendor/github.com/kolo/xmlrpc/is_zero.go
@@ -0,0 +1,44 @@
+package xmlrpc
+
+import (
+ "math"
+ . "reflect"
+)
+
+func isZero(v Value) bool {
+ switch v.Kind() {
+ case Bool:
+ return !v.Bool()
+ case Int, Int8, Int16, Int32, Int64:
+ return v.Int() == 0
+ case Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
+ return v.Uint() == 0
+ case Float32, Float64:
+ return math.Float64bits(v.Float()) == 0
+ case Complex64, Complex128:
+ c := v.Complex()
+ return math.Float64bits(real(c)) == 0 && math.Float64bits(imag(c)) == 0
+ case Array:
+ for i := 0; i < v.Len(); i++ {
+ if !isZero(v.Index(i)) {
+ return false
+ }
+ }
+ return true
+ case Chan, Func, Interface, Map, Ptr, Slice, UnsafePointer:
+ return v.IsNil()
+ case String:
+ return v.Len() == 0
+ case Struct:
+ for i := 0; i < v.NumField(); i++ {
+ if !isZero(v.Field(i)) {
+ return false
+ }
+ }
+ return true
+ default:
+ // This should never happens, but will act as a safeguard for
+ // later, as a default value doesn't makes sense here.
+ panic(&ValueError{"reflect.Value.IsZero", v.Kind()})
+ }
+}
diff --git a/vendor/github.com/kolo/xmlrpc/response.go b/vendor/github.com/kolo/xmlrpc/response.go
index 6742a1c74..18e6d366c 100644
--- a/vendor/github.com/kolo/xmlrpc/response.go
+++ b/vendor/github.com/kolo/xmlrpc/response.go
@@ -1,6 +1,7 @@
package xmlrpc
import (
+ "fmt"
"regexp"
)
@@ -8,43 +9,32 @@ var (
faultRx = regexp.MustCompile(`(\s|\S)+`)
)
-type failedResponse struct {
- Code int `xmlrpc:"faultCode"`
- Error string `xmlrpc:"faultString"`
+// FaultError is returned from the server when an invalid call is made
+type FaultError struct {
+ Code int `xmlrpc:"faultCode"`
+ String string `xmlrpc:"faultString"`
}
-func (r *failedResponse) err() error {
- return &xmlrpcError{
- code: r.Code,
- err: r.Error,
+// Error implements the error interface
+func (e FaultError) Error() string {
+ return fmt.Sprintf("Fault(%d): %s", e.Code, e.String)
+}
+
+type Response []byte
+
+func (r Response) Err() error {
+ if !faultRx.Match(r) {
+ return nil
}
-}
-
-type Response struct {
- data []byte
-}
-
-func NewResponse(data []byte) *Response {
- return &Response{
- data: data,
- }
-}
-
-func (r *Response) Failed() bool {
- return faultRx.Match(r.data)
-}
-
-func (r *Response) Err() error {
- failedResp := new(failedResponse)
- if err := unmarshal(r.data, failedResp); err != nil {
+ var fault FaultError
+ if err := unmarshal(r, &fault); err != nil {
return err
}
-
- return failedResp.err()
+ return fault
}
-func (r *Response) Unmarshal(v interface{}) error {
- if err := unmarshal(r.data, v); err != nil {
+func (r Response) Unmarshal(v interface{}) error {
+ if err := unmarshal(r, v); err != nil {
return err
}
diff --git a/vendor/github.com/kolo/xmlrpc/test_server.rb b/vendor/github.com/kolo/xmlrpc/test_server.rb
index 1b1ff8760..1ccfc9ac4 100644
--- a/vendor/github.com/kolo/xmlrpc/test_server.rb
+++ b/vendor/github.com/kolo/xmlrpc/test_server.rb
@@ -15,9 +15,9 @@ class Service
x + y
end
- def error
- raise XMLRPC::FaultException.new(500, "Server error")
- end
+ def error
+ raise XMLRPC::FaultException.new(500, "Server error")
+ end
end
server = XMLRPC::Server.new 5001, 'localhost'
diff --git a/vendor/github.com/kolo/xmlrpc/xmlrpc.go b/vendor/github.com/kolo/xmlrpc/xmlrpc.go
deleted file mode 100644
index 8766403af..000000000
--- a/vendor/github.com/kolo/xmlrpc/xmlrpc.go
+++ /dev/null
@@ -1,19 +0,0 @@
-package xmlrpc
-
-import (
- "fmt"
-)
-
-// xmlrpcError represents errors returned on xmlrpc request.
-type xmlrpcError struct {
- code int
- err string
-}
-
-// Error() method implements Error interface
-func (e *xmlrpcError) Error() string {
- return fmt.Sprintf("error: \"%s\" code: %d", e.err, e.code)
-}
-
-// Base64 represents value in base64 encoding
-type Base64 string
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 48cd3997f..55011c733 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -119,7 +119,7 @@ github.com/gophercloud/gophercloud/pagination
github.com/jmespath/go-jmespath
# github.com/julienschmidt/httprouter v1.2.0
github.com/julienschmidt/httprouter
-# github.com/kolo/xmlrpc v0.0.0-20190417161013-de6d879202d7
+# github.com/kolo/xmlrpc v0.0.0-20200310150728-e0350524596b
github.com/kolo/xmlrpc
# github.com/kr/pretty v0.1.0
github.com/kr/pretty