From 07ec6b961749653c4fec18d47a33fdbb0c09927c Mon Sep 17 00:00:00 2001 From: NitishKumar06 Date: Wed, 20 Sep 2023 17:37:02 +0530 Subject: [PATCH 1/2] add initial library functions: DELETE --- obs/error.go | 38 +++++++++++++++++ obs/project.go | 111 ++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 147 insertions(+), 2 deletions(-) create mode 100644 obs/error.go diff --git a/obs/error.go b/obs/error.go new file mode 100644 index 0000000..f5d703e --- /dev/null +++ b/obs/error.go @@ -0,0 +1,38 @@ +/* +Copyright 2023 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package obs + +import ( + "encoding/xml" + "fmt" +) + +type Status struct { + XMLName xml.Name `json:"status" xml:"status"` + Code string `json:"code" xml:"code,attr"` + Summary string `json:"summary" xml:"summary"` +} + +type APIError struct { + HTTPStatusCode int + OBSStatusCode string + Message string +} + +func (e *APIError) Error() string { + return fmt.Sprintf("HTTP status %d: %s (%s)", e.HTTPStatusCode, e.OBSStatusCode, e.Message) +} diff --git a/obs/project.go b/obs/project.go index 2682f24..660bf62 100644 --- a/obs/project.go +++ b/obs/project.go @@ -17,7 +17,12 @@ limitations under the License. package obs import ( + "bytes" + "context" "encoding/xml" + "fmt" + "net/http" + "net/url" ) type Project struct { @@ -36,6 +41,7 @@ type Project struct { } type Client struct { + Client http.Client Username string Password string APIURL string @@ -76,8 +82,8 @@ const ( type Repository struct { Repository string `json:"name" xml:"name,attr"` - Architectures []string `json:"arch" xml:"arch"` - ReleaseTargets []ReleaseTarget `json:"releasetarget,omitempty" xml:"releasetarget,omitempty"` + Architectures []string `json:"architectures" xml:"arch"` + ReleaseTargets []ReleaseTarget `json:"releaseTargets,omitempty" xml:"releasetarget,omitempty"` Paths []RepositoryPath `json:"path,omitempty" xml:"path,omitempty"` } @@ -91,3 +97,104 @@ type RepositoryPath struct { Project string `json:"project" xml:"project,attr"` Repository string `json:"repository" xml:"repository,attr"` } + +func (c *Client) CreateUpdateProject(project *Project, ctx context.Context) error { + xmlData, err := xml.MarshalIndent(project, "", " ") + if err != nil { + return fmt.Errorf("creating obs project: marshalling project meta: %w", err) + } + + urlPath, err := url.JoinPath(c.APIURL, "source", project.Name, "_meta") + if err != nil { + return fmt.Errorf("creating obs project: joining url: %w", err) + } + + req, err := http.NewRequestWithContext(ctx, http.MethodPut, urlPath, bytes.NewBuffer(xmlData)) + if err != nil { + return &APIError{ + HTTPStatusCode: 0, + OBSStatusCode: "", + Message: fmt.Sprintf("creating obs project: creating request: %v", err), + } + } + + req.SetBasicAuth(c.Username, c.Password) + req.Header.Set("Accept", "application/xml; charset=utf-8") + + resp, err := c.Client.Do(req) + if err != nil { + return &APIError{ + HTTPStatusCode: 0, + OBSStatusCode: "", + Message: fmt.Sprintf("creating obs project: sending request: %v", err), + } + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + var status Status + if err := xml.NewDecoder(resp.Body).Decode(&status); err != nil { + return &APIError{ + HTTPStatusCode: resp.StatusCode, + OBSStatusCode: "", + Message: fmt.Sprintf("creating obs project: decoding error response: %v", err), + } + } + + return &APIError{ + HTTPStatusCode: resp.StatusCode, + OBSStatusCode: status.Code, + Message: status.Summary, + } + } + + return nil +} + +func (c *Client) DeleteProject(project *Project, ctx context.Context) error { + urlPath, err := url.JoinPath(c.APIURL, "source", project.Name) + if err != nil { + return fmt.Errorf("deleting obs project: joining url: %w", err) + } + + req, err := http.NewRequestWithContext(ctx, http.MethodDelete, urlPath, http.NoBody) + if err != nil { + return &APIError{ + HTTPStatusCode: 0, + OBSStatusCode: "", + Message: fmt.Sprintf("deleting obs project: creating request: %v", err), + } + } + + req.SetBasicAuth(c.Username, c.Password) + req.Header.Set("Accept", "application/xml; charset=utf-8") + + resp, err := c.Client.Do(req) + if err != nil { + return &APIError{ + HTTPStatusCode: 0, + OBSStatusCode: "", + Message: fmt.Sprintf("deleting obs project: sending request: %v", err), + } + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + var status Status + if err := xml.NewDecoder(resp.Body).Decode(&status); err != nil { + return &APIError{ + HTTPStatusCode: resp.StatusCode, + OBSStatusCode: "", + Message: fmt.Sprintf("deleting obs project: decoding error response %v", err), + } + } + + return &APIError{ + HTTPStatusCode: resp.StatusCode, + OBSStatusCode: status.Code, + Message: status.Summary, + } + } + + return nil +} From 78479be1e13200506f823893b4e89db5c477b883 Mon Sep 17 00:00:00 2001 From: NitishKumar06 Date: Fri, 29 Sep 2023 19:23:13 +0530 Subject: [PATCH 2/2] marked suggestions Signed-off-by: NitishKumar06 --- obs/project.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/obs/project.go b/obs/project.go index 660bf62..6a36e73 100644 --- a/obs/project.go +++ b/obs/project.go @@ -98,7 +98,7 @@ type RepositoryPath struct { Repository string `json:"repository" xml:"repository,attr"` } -func (c *Client) CreateUpdateProject(project *Project, ctx context.Context) error { +func (c *Client) CreateUpdateProject(ctx context.Context, project *Project) error { xmlData, err := xml.MarshalIndent(project, "", " ") if err != nil { return fmt.Errorf("creating obs project: marshalling project meta: %w", err) @@ -151,7 +151,7 @@ func (c *Client) CreateUpdateProject(project *Project, ctx context.Context) erro return nil } -func (c *Client) DeleteProject(project *Project, ctx context.Context) error { +func (c *Client) DeleteProject(ctx context.Context, project *Project) error { urlPath, err := url.JoinPath(c.APIURL, "source", project.Name) if err != nil { return fmt.Errorf("deleting obs project: joining url: %w", err)