mirror of
https://github.com/SAP/jenkins-library.git
synced 2025-01-08 04:21:26 +02:00
0ba4c2206c
* 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>
199 lines
6.1 KiB
Go
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
|
|
}
|