github.com/ouraigua/jenkins-library@v0.0.0-20231028010029-fbeaf2f3aa9b/pkg/abap/aakaas/targetVector.go (about)

     1  package aakaas
     2  
     3  import (
     4  	"encoding/json"
     5  	"net/http"
     6  	"net/url"
     7  	"time"
     8  
     9  	abapbuild "github.com/SAP/jenkins-library/pkg/abap/build"
    10  	"github.com/SAP/jenkins-library/pkg/abaputils"
    11  	"github.com/pkg/errors"
    12  )
    13  
    14  // TargetVectorStatus : Status of TargetVector in AAKaaS
    15  type TargetVectorStatus string
    16  
    17  const (
    18  	// TargetVectorStatusGenerated : TargetVector is Generated (not published yet)
    19  	TargetVectorStatusGenerated TargetVectorStatus = "G"
    20  	// TargetVectorStatusTest : TargetVector is published for testing
    21  	TargetVectorStatusTest TargetVectorStatus = "T"
    22  	// TargetVectorStatusProductive : TargetVector is published for productive use
    23  	TargetVectorStatusProductive TargetVectorStatus = "P"
    24  
    25  	TargetVectorPublishStatusRunning TargetVectorStatus = "R"
    26  	TargetVectorPublishStatusSuccess TargetVectorStatus = "S"
    27  	TargetVectorPublishStatusError   TargetVectorStatus = "E"
    28  )
    29  
    30  // internal usage : Json Structure for AAKaaS Odata Service
    31  type jsonTargetVector struct {
    32  	Tv *TargetVector `json:"d"`
    33  }
    34  
    35  // TargetVector : TargetVector desribes a deployble state of an ABAP product version
    36  type TargetVector struct {
    37  	ID             string          `json:"Id"`
    38  	ProductName    string          `json:"ProductName"`
    39  	ProductVersion string          `json:"ProductVersion"`
    40  	SpsLevel       string          `json:"SpsLevel"`
    41  	PatchLevel     string          `json:"PatchLevel"`
    42  	Status         string          `json:"Status"`
    43  	PublishStatus  string          `json:"PublishStatus"`
    44  	Content        TargetVectorCVs `json:"Content"`
    45  }
    46  
    47  // TargetVectorCV : deployable state of an software Component Version as part of an TargetVector
    48  type TargetVectorCV struct {
    49  	ID              string `json:"Id"`
    50  	ScName          string `json:"ScName"`
    51  	ScVersion       string `json:"ScVersion"`
    52  	DeliveryPackage string `json:"DeliveryPackage"`
    53  	SpLevel         string `json:"SpLevel"`
    54  	PatchLevel      string `json:"PatchLevel"`
    55  }
    56  
    57  // TargetVectorCVs : deployable states of the software Component Versions of the product version
    58  type TargetVectorCVs struct {
    59  	TargetVectorCVs []TargetVectorCV `json:"results"`
    60  }
    61  
    62  // Init : Initialize TargetVector for Creation in AAKaaS
    63  func (tv *TargetVector) InitNew(addonDescriptor *abaputils.AddonDescriptor) error {
    64  	if addonDescriptor.AddonProduct == "" || addonDescriptor.AddonVersion == "" || addonDescriptor.AddonSpsLevel == "" || addonDescriptor.AddonPatchLevel == "" {
    65  		return errors.New("Parameters missing. Please provide product name, version, spslevel and patchlevel")
    66  	}
    67  	tv.ProductName = addonDescriptor.AddonProduct
    68  	tv.ProductVersion = addonDescriptor.AddonVersion
    69  	tv.SpsLevel = addonDescriptor.AddonSpsLevel
    70  	tv.PatchLevel = addonDescriptor.AddonPatchLevel
    71  
    72  	var tvCVs []TargetVectorCV
    73  	var tvCV TargetVectorCV
    74  	for i := range addonDescriptor.Repositories {
    75  		if addonDescriptor.Repositories[i].Name == "" || addonDescriptor.Repositories[i].Version == "" || addonDescriptor.Repositories[i].SpLevel == "" ||
    76  			addonDescriptor.Repositories[i].PatchLevel == "" || addonDescriptor.Repositories[i].PackageName == "" {
    77  			return errors.New("Parameters missing. Please provide software component name, version, splevel, patchlevel and packagename")
    78  		}
    79  		tvCV.ScName = addonDescriptor.Repositories[i].Name
    80  		tvCV.ScVersion = addonDescriptor.Repositories[i].Version
    81  		tvCV.DeliveryPackage = addonDescriptor.Repositories[i].PackageName
    82  		tvCV.SpLevel = addonDescriptor.Repositories[i].SpLevel
    83  		tvCV.PatchLevel = addonDescriptor.Repositories[i].PatchLevel
    84  		tvCVs = append(tvCVs, tvCV)
    85  	}
    86  	tv.Content.TargetVectorCVs = tvCVs
    87  	return nil
    88  }
    89  
    90  // InitExisting : Initialize an already in AAKaaS existing TargetVector
    91  func (tv *TargetVector) InitExisting(ID string) {
    92  	tv.ID = ID
    93  }
    94  
    95  // CreateTargetVector : Initial Creation of an TargetVector
    96  func (tv *TargetVector) CreateTargetVector(conn *abapbuild.Connector) error {
    97  	conn.GetToken("/odata/aas_ocs_package")
    98  	tvJSON, err := json.Marshal(tv)
    99  	if err != nil {
   100  		return errors.Wrap(err, "Generating Request Data for Create Target Vector failed")
   101  	}
   102  	appendum := "/odata/aas_ocs_package/TargetVectorSet"
   103  	body, err := conn.Post(appendum, string(tvJSON))
   104  	if err != nil {
   105  		return errors.Wrap(err, "Creating Target Vector in AAKaaS failed")
   106  	}
   107  	var jTV jsonTargetVector
   108  	if err := json.Unmarshal(body, &jTV); err != nil {
   109  		return errors.Wrap(err, "Unexpected AAKaaS response for create target vector: "+string(body))
   110  	}
   111  	tv.ID = jTV.Tv.ID
   112  	tv.Status = jTV.Tv.Status
   113  	return nil
   114  }
   115  
   116  func (tv *TargetVector) PublishTargetVector(conn *abapbuild.Connector, targetVectorScope TargetVectorStatus) error {
   117  	conn.GetToken("/odata/aas_ocs_package")
   118  	appendum := "/odata/aas_ocs_package/PublishTargetVector?Id='" + url.QueryEscape(tv.ID) + "'&Scope='" + url.QueryEscape(string(targetVectorScope)) + "'"
   119  	body, err := conn.Post(appendum, "")
   120  	if err != nil {
   121  		return errors.Wrap(err, "Publish Target Vector in AAKaaS failed")
   122  	}
   123  
   124  	var jTV jsonTargetVector
   125  	if err := json.Unmarshal(body, &jTV); err != nil {
   126  		return errors.Wrap(err, "Unexpected AAKaaS response for publish target vector: "+string(body))
   127  	}
   128  
   129  	tv.Status = jTV.Tv.Status
   130  	tv.PublishStatus = jTV.Tv.PublishStatus
   131  	return nil
   132  }
   133  
   134  // GetTargetVector : Read details of the TargetVector
   135  func (tv *TargetVector) GetTargetVector(conn *abapbuild.Connector) error {
   136  	if tv.ID == "" {
   137  		return errors.New("Without ID no details of a targetVector can be obtained from AAKaaS")
   138  	}
   139  	appendum := "/odata/aas_ocs_package/TargetVectorSet('" + url.QueryEscape(tv.ID) + "')"
   140  	body, err := conn.Get(appendum)
   141  	if err != nil {
   142  		return errors.Wrap(err, "Getting Target Vector details from AAKaaS failed")
   143  	}
   144  
   145  	var jTV jsonTargetVector
   146  	if err := json.Unmarshal(body, &jTV); err != nil {
   147  		return errors.Wrap(err, "Unexpected AAKaaS response for getting target vector details: "+string(body))
   148  	}
   149  
   150  	tv.Status = jTV.Tv.Status
   151  	tv.PublishStatus = jTV.Tv.PublishStatus
   152  	//other fields not needed atm
   153  	return nil
   154  }
   155  
   156  // PollForStatus : Poll AAKaaS until final PublishStatus reached and check if desired Status was reached
   157  func (tv *TargetVector) PollForStatus(conn *abapbuild.Connector, targetStatus TargetVectorStatus) error {
   158  	timeout := time.After(conn.MaxRuntime)
   159  	ticker := time.Tick(conn.PollingInterval)
   160  	for {
   161  		select {
   162  		case <-timeout:
   163  			return errors.New("Timed out (AAKaaS target Vector Status change)")
   164  		case <-ticker:
   165  			if err := tv.GetTargetVector(conn); err != nil {
   166  				return errors.Wrap(err, "Getting TargetVector status during polling resulted in an error")
   167  			}
   168  			switch TargetVectorStatus(tv.PublishStatus) {
   169  			case TargetVectorPublishStatusRunning:
   170  				continue
   171  			case TargetVectorPublishStatusSuccess:
   172  				if TargetVectorStatus(tv.Status) == targetStatus {
   173  					return nil
   174  				} else {
   175  					return errors.New("Publishing of Targetvector " + tv.ID + " resulted in state " + string(tv.Status) + "instead of expected state " + string(targetStatus))
   176  				}
   177  			case TargetVectorPublishStatusError:
   178  				return errors.New("Publishing of Targetvector " + tv.ID + " failed in AAKaaS")
   179  			default:
   180  				return errors.New("Polling returned invalid TargetVectorPublishStatus: " + string(tv.PublishStatus))
   181  			}
   182  		}
   183  	}
   184  }
   185  
   186  /****************
   187   Mock Client Data
   188  ****************/
   189  
   190  var AAKaaSHead = abapbuild.MockData{
   191  	Method: `HEAD`,
   192  	Url:    `/odata/aas_ocs_package`,
   193  	Body: `<?xml version="1.0"?>
   194  	<HTTP_BODY/>`,
   195  	StatusCode: 200,
   196  	Header:     http.Header{"x-csrf-token": {"HRfJP0OhB9C9mHs2RRqUzw=="}},
   197  }
   198  
   199  var AAKaaSTVPublishTestPost = abapbuild.MockData{
   200  	Method: `POST`,
   201  	Url:    `/odata/aas_ocs_package/PublishTargetVector?Id='W7Q00207512600000353'&Scope='T'`,
   202  	Body: `{
   203  		"d": {
   204  			"Id": "W7Q00207512600000353",
   205  			"Vendor": "0000029218",
   206  			"ProductName": "/DRNMSPC/PRD01",
   207  			"ProductVersion": "0001",
   208  			"SpsLevel": "0000",
   209  			"PatchLevel": "0000",
   210  			"Status": "G",
   211  			"PublishStatus": "R"
   212  		}
   213  	}`,
   214  	StatusCode: 200,
   215  }
   216  
   217  var AAKaaSTVPublishProdPost = abapbuild.MockData{
   218  	Method: `POST`,
   219  	Url:    `/odata/aas_ocs_package/PublishTargetVector?Id='W7Q00207512600000353'&Scope='P'`,
   220  	Body: `{
   221  		"d": {
   222  			"Id": "W7Q00207512600000353",
   223  			"Vendor": "0000029218",
   224  			"ProductName": "/DRNMSPC/PRD01",
   225  			"ProductVersion": "0001",
   226  			"SpsLevel": "0000",
   227  			"PatchLevel": "0000",
   228  			"Status": "G",
   229  			"PublishStatus": "R"
   230  		}
   231  	}`,
   232  	StatusCode: 200,
   233  }
   234  
   235  var AAKaaSGetTVPublishRunning = abapbuild.MockData{
   236  	Method: `GET`,
   237  	Url:    `/odata/aas_ocs_package/TargetVectorSet('W7Q00207512600000353')`,
   238  	Body: `{
   239  		"d": {
   240  			"Id": "W7Q00207512600000353",
   241  			"Vendor": "0000029218",
   242  			"ProductName": "/DRNMSPC/PRD01",
   243  			"ProductVersion": "0001",
   244  			"SpsLevel": "0000",
   245  			"PatchLevel": "0000",
   246  			"Status": "G",
   247  			"PublishStatus": "R"
   248  		}
   249  	}`,
   250  	StatusCode: 200,
   251  }
   252  
   253  var AAKaaSGetTVPublishTestSuccess = abapbuild.MockData{
   254  	Method: `GET`,
   255  	Url:    `/odata/aas_ocs_package/TargetVectorSet('W7Q00207512600000353')`,
   256  	Body: `{
   257  		"d": {
   258  			"Id": "W7Q00207512600000353",
   259  			"Vendor": "0000029218",
   260  			"ProductName": "/DRNMSPC/PRD01",
   261  			"ProductVersion": "0001",
   262  			"SpsLevel": "0000",
   263  			"PatchLevel": "0000",
   264  			"Status": "T",
   265  			"PublishStatus": "S"
   266  		}
   267  	}`,
   268  	StatusCode: 200,
   269  }
   270  
   271  var AAKaaSGetTVPublishProdSuccess = abapbuild.MockData{
   272  	Method: `GET`,
   273  	Url:    `/odata/aas_ocs_package/TargetVectorSet('W7Q00207512600000353')`,
   274  	Body: `{
   275  		"d": {
   276  			"Id": "W7Q00207512600000353",
   277  			"Vendor": "0000029218",
   278  			"ProductName": "/DRNMSPC/PRD01",
   279  			"ProductVersion": "0001",
   280  			"SpsLevel": "0000",
   281  			"PatchLevel": "0000",
   282  			"Status": "P",
   283  			"PublishStatus": "S"
   284  		}
   285  	}`,
   286  	StatusCode: 200,
   287  }
   288  
   289  var AAKaaSTVCreatePost = abapbuild.MockData{
   290  	Method: `POST`,
   291  	Url:    `/odata/aas_ocs_package/TargetVectorSet`,
   292  	Body: `{
   293  		"d": {
   294  			"Id": "W7Q00207512600000262",
   295  			"Vendor": "0000203069",
   296  			"ProductName": "/DRNMSPC/PRD01",
   297  			"ProductVersion": "0001",
   298  			"SpsLevel": "0000",
   299  			"PatchLevel": "0000",
   300  			"Status": "G",
   301  			"Content": {
   302  				"results": [
   303  					{
   304  						"Id": "W7Q00207512600000262",
   305  						"ScName": "/DRNMSPC/COMP01",
   306  						"ScVersion": "0001",
   307  						"DeliveryPackage": "SAPK-001AAINDRNMSPC",
   308  						"SpLevel": "0000",
   309  						"PatchLevel": "0000"
   310  					}
   311  				]
   312  			}
   313  		}
   314  	}`,
   315  	StatusCode: 200,
   316  }
   317  
   318  var templateMockData = abapbuild.MockData{
   319  	Method:     `GET`,
   320  	Url:        ``,
   321  	Body:       ``,
   322  	StatusCode: 200,
   323  }