1
0
mirror of https://github.com/SAP/jenkins-library.git synced 2025-01-08 04:21:26 +02:00
sap-jenkins-library/pkg/asc/asc.go
Jordi van Liempt 0ba4c2206c
chore(deps): Replace io/ioutil package (#4494)
* update all deprecated ioutil usages

* forgotten changes

* add missing imports

* undo changing comment

* add missing 'os' import

* fix integration test

---------

Co-authored-by: I557621 <jordi.van.liempt@sap.com>
Co-authored-by: Gulom Alimov <gulomjon.alimov@sap.com>
2023-08-16 12:57:04 +02:00

199 lines
6.1 KiB
Go

package asc
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
url2 "net/url"
"strconv"
"strings"
"time"
piperHttp "github.com/SAP/jenkins-library/pkg/http"
"github.com/SAP/jenkins-library/pkg/log"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
type App struct {
AppId int `json:"app_id"`
AppName string `json:"app_name"`
BundleId string `json:"bundle_id"`
JamfId string `json:"jamf_id"`
}
type JamfAppInformationResponse struct {
MobileDeviceApplication JamfMobileDeviceApplication `json:"mobile_device_application"`
}
type JamfMobileDeviceApplication struct {
General JamfMobileDeviceApplicationGeneral `json:"general"`
}
type JamfMobileDeviceApplicationGeneral struct {
Id int `json:"id"`
}
type CreateReleaseResponse struct {
Status string `json:"status"`
Message string `json:"message"`
LastID int `json:"lastID"`
Data Release `json:"data"`
}
type Release struct {
ReleaseID int `json:"release_id"`
AppID int `json:"app_id"`
Version string `json:"version"`
Description string `json:"description"`
ReleaseDate time.Time `json:"release_date"`
SortOrder any `json:"sort_order"`
Visible bool `json:"visible"`
Created time.Time `json:"created"`
FileMetadata any `json:"file_metadata"`
}
// SystemInstance is the client communicating with the ASC backend
type SystemInstance struct {
serverURL string
token string
client *piperHttp.Client
logger *logrus.Entry
}
type System interface {
GetAppById(appId string) (App, error)
CreateRelease(ascAppId int, version string, description string, releaseDate string, visible bool) (CreateReleaseResponse, error)
GetJamfAppInfo(bundleId string, jamfTargetSystem string) (JamfAppInformationResponse, error)
UploadIpa(path string, jamfAppId int, jamfTargetSystem string, bundleId string, ascRelease Release) error
}
// NewSystemInstance returns a new ASC client for communicating with the backend
func NewSystemInstance(client *piperHttp.Client, serverURL, token string) (*SystemInstance, error) {
loggerInstance := log.Entry().WithField("package", "SAP/jenkins-library/pkg/asc")
if len(serverURL) == 0 {
return nil, errors.New("serverUrl is not set but required")
}
if len(token) == 0 {
return nil, errors.New("AppToken is not set but required")
}
sys := &SystemInstance{
serverURL: strings.TrimSuffix(serverURL, "/"),
token: token,
client: client,
logger: loggerInstance,
}
log.RegisterSecret(token)
options := piperHttp.ClientOptions{
Token: fmt.Sprintf("Bearer %s", sys.token),
TransportTimeout: time.Second * 15,
}
sys.client.SetOptions(options)
return sys, nil
}
func sendRequest(sys *SystemInstance, method, url string, body io.Reader, header http.Header) ([]byte, error) {
var requestBody io.Reader
if body != nil {
closer := io.NopCloser(body)
bodyBytes, _ := io.ReadAll(closer)
requestBody = bytes.NewBuffer(bodyBytes)
defer closer.Close()
}
response, err := sys.client.SendRequest(method, fmt.Sprintf("%v/%v", sys.serverURL, url), requestBody, header, nil)
if err != nil && (response == nil) {
sys.logger.Errorf("HTTP request failed with error: %s", err)
return nil, err
}
data, _ := io.ReadAll(response.Body)
sys.logger.Debugf("Valid response body: %v", string(data))
defer response.Body.Close()
return data, nil
}
// GetAppById returns the app addressed by appId from the ASC backend
func (sys *SystemInstance) GetAppById(appId string) (App, error) {
sys.logger.Debugf("Getting ASC App with ID %v...", appId)
var app App
data, err := sendRequest(sys, http.MethodGet, fmt.Sprintf("api/v1/apps/%v", appId), nil, nil)
if err != nil {
return app, errors.Wrapf(err, "fetching app %v failed", appId)
}
json.Unmarshal(data, &app)
return app, nil
}
// CreateRelease creates a release in ASC
func (sys *SystemInstance) CreateRelease(ascAppId int, version string, description string, releaseDate string, visible bool) (CreateReleaseResponse, error) {
var createReleaseResponse CreateReleaseResponse
if len(releaseDate) == 0 {
currentTime := time.Now()
releaseDate = currentTime.Format("01/02/2006")
}
jsonData := map[string]string{
"version": version,
"description": description,
"release_date": releaseDate,
"visible": strconv.FormatBool(visible),
}
jsonValue, err := json.Marshal(jsonData)
if err != nil {
return createReleaseResponse, errors.Wrap(err, "error marshalling release payload")
}
header := http.Header{}
header.Set("Content-Type", "application/json")
response, err := sendRequest(sys, http.MethodPost, fmt.Sprintf("api/v1/apps/%v/releases", ascAppId), bytes.NewBuffer(jsonValue), header)
if err != nil {
return createReleaseResponse, errors.Wrapf(err, "creating release")
}
json.Unmarshal(response, &createReleaseResponse)
return createReleaseResponse, nil
}
// GetJamfAppInfo fetches information about the app from Jamf
func (sys *SystemInstance) GetJamfAppInfo(bundleId string, jamfTargetSystem string) (JamfAppInformationResponse, error) {
sys.logger.Debugf("Getting Jamf App Info by ID %v from jamf %v system...", bundleId, jamfTargetSystem)
var jamfAppInformationResponse JamfAppInformationResponse
data, err := sendRequest(sys, http.MethodPost, fmt.Sprintf("api/v1/jamf/%v/info?system=%v", bundleId, url2.QueryEscape(jamfTargetSystem)), nil, nil)
if err != nil {
return jamfAppInformationResponse, errors.Wrapf(err, "fetching jamf %v app info for %v failed", jamfTargetSystem, bundleId)
}
json.Unmarshal(data, &jamfAppInformationResponse)
return jamfAppInformationResponse, nil
}
// UploadIpa uploads the ipa to ASC and therewith to Jamf
func (sys *SystemInstance) UploadIpa(path string, jamfAppId int, jamfTargetSystem string, bundleId string, ascRelease Release) error {
url := fmt.Sprintf("%v/api/v1/jamf/%v/ipa?app_id=%v&version=%v&system=%v&release_id=%v&bundle_id=%v", sys.serverURL, jamfAppId, ascRelease.AppID, url2.QueryEscape(ascRelease.Version), url2.QueryEscape(jamfTargetSystem), ascRelease.ReleaseID, url2.QueryEscape(bundleId))
_, err := sys.client.UploadFile(url, path, "file", nil, nil, "form")
if err != nil {
return errors.Wrap(err, "failed to upload ipa to asc")
}
return nil
}