Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: xray watch #211

Merged
merged 30 commits into from
Nov 9, 2020
Merged

Feature: xray watch #211

merged 30 commits into from
Nov 9, 2020

Conversation

josh-barker-coles
Copy link
Contributor

Description:

This PR creates:

  • an Xray Manager that uses a separate endpoint
  • a function to retrieve the Xray Version - GetXrayVersion
  • functions to Create, Get, Update and Delete an Xray Watch
    • CreateXrayWatch
    • GetXrayWatch
    • UpdateXrayWatch
    • DeleteXrayWatch

The Xray Watch functions support the configuration of Repositories and Builds.

There is a placeholder method to configure Bundles.
I can't implement the support for Bundles because of the limits on the free trial for artifactory.

Related Issues

Resolves #202

@github-actions
Copy link
Contributor

github-actions bot commented Oct 14, 2020

CLA Assistant Lite bot All contributors have signed the CLA ✍️

@josh-barker-coles
Copy link
Contributor Author

I have read the CLA Document and I hereby sign the CLA

@josh-barker-coles
Copy link
Contributor Author

recheckcla

@josh-barker-coles
Copy link
Contributor Author

Hi @eyalbe4, it would be good to get your review on this.

Cheers

@eyalbe4
Copy link
Contributor

eyalbe4 commented Oct 16, 2020

Sure @josh-barker-coles.
I'll get to reviewing this soon.

Copy link
Contributor

@eyalbe4 eyalbe4 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't gone through everything yet. Releasing what I have so far.

if *DistUrl != "" {
createDistributionManager()
}
if *XrayUrl != "" {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that this has been added as part of the InitArtifactoryServiceManager function, we should probably rename the function from InitArtifactoryServiceManager to InitServiceManagers.

@@ -158,6 +167,14 @@ func createDistributionManager() {
testsBundleDeleteRemoteService.DistDetails = distDetails
}

func createXrayManager() {
xrayDetails := GetXrayDetails()
client, err := rthttpclient.ArtifactoryClientBuilder().SetServiceDetails(&xrayDetails).Build()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that ArtifactoryClientBuilder also needs to be used for Xray, we should rename it to HttpClientBuilder.
We should also move the httpclient package, which is currently located under the artifactory directory, to be one level up, next to the artifactory dir.
rthttpclient should be renamed to httpclient, or if the the httpclient is already taken as an alias in the file, maybe jfroghttpclient.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @eyalbe4,

I understand why you want to move that functionality, but I've noticed a few things.

This sounds like a big change that should go in a separate PR, as it would effect many files under artifactory/*, distribution/*, tests/* and xray/*.

As the httpclient directory & package is already taken, what did you want to do?

Cheers

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it @josh-barker-coles. We'll create an issue for this and handle this in a follow up PR.

tests/utils.go Outdated
@@ -158,6 +167,14 @@ func createDistributionManager() {
testsBundleDeleteRemoteService.DistDetails = distDetails
}

func createXrayManager() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For consistency, this function should be renamed to * createXrayVersionManager*.

AssignedPolicies []XrayAssignedPolicy `json:"assigned_policies,omitempty"`
}

// structs that aren't exported
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does "exported" mean?
BTW, our convention is is to start all comments with an upper case letter.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@eyalbe4
If a struct or function starts with an upper case, it's available in the package to be imported somewhere else.
However, if a struct or function starts with a lower case, it's internal and cannot be imported elsewhere.

As these structs are used for internally transforming the parameters to the payload, I opted to not export them.
What would you prefer?

payloadBody.ProjectResources.Resources = append(payloadBody.ProjectResources.Resources, repo)
}
case "":
// empty is fine
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// empty is fine --> // Empty is fine

case "":
// empty is fine
default:
return errors.New("Invalid Repository Type. Must be " + string(WatchRepositoriesAll) + " or " + string(WatchRepositoriesByName))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should wrap this error with errorutils.CheckError(err)..
In this case, the above line should:

errorutils.CheckError(errors.New("Invalid Repository Type. Must be " + string(WatchRepositoriesAll) + " or " + string(WatchRepositoriesByName)))

errorutils.CheckError is used to wrap the error when it is created by the code, or if it is created by the code of an external package, the error is wrapped the first time it is returned in the code. This approach allows us to track the source code generating the error if needed.
I noticed there's one more place in this file where this si needed.

return nil
}

func configureBundles(payloadBody *XrayWatchBody, params XrayWatchParams) error {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We prefer not to have placeholder code in the form of empty methods. I suggest you to the description of the CreateBody function a comment saying that bundles are currently not supported. This disclaimer should also be added to the API description in the README.

Copy link
Contributor

@eyalbe4 eyalbe4 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done reviewing everything.
Thanks so much for adding this!
See my inline comments.

assert.Equal(t, params.Description, targetConfig.Description)
assert.Equal(t, params.Active, targetConfig.Active)
assert.Equal(t, params.Policies, targetConfig.Policies)
return
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant return statement.

artUtils.SetContentType("application/json", &xrayHTTPDetails.Headers)
client, err := httpclient.ClientBuilder().Build()
if err != nil {
return nil
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should probably be fixed to return err.

resp, _, err := client.SendDelete(xrayDetails.GetUrl()+"api/v2/policies/"+policyName, nil, xrayHTTPDetails)
if err != nil || resp.StatusCode != http.StatusOK {
return errors.New("failed to delete policy " + resp.Status)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest changing the above to:

	if err != nil  {
		return error
	}
	if resp.StatusCode != http.StatusOK {
		return errors.New("failed to delete policy " + resp.Status)
	}

This also applies to other checks in this file.

"net/http"

rthttpclient "github.com/jfrog/jfrog-client-go/artifactory/httpclient"
// "github.com/jfrog/jfrog-client-go/artifactory/services/utils"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's remove this commented line.

)

// XrayWatchService defines the http client and xray details
type XrayWatchService struct {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ket's rename the struct to WatchService and this file to watch.go.
Let's also rename NewXrayWatchService to NewWatchService.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@eyalbe4

Most, if not all, structs have a prefix of Xray.
Did you want them all to be renamed without Xray?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @eyalbe4, I've renamed all structs & functions that included Xray.

return nil
}

// Get retrieves the details about an Xray watch by name
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// Get retrieves the details about an Xray watch by name --> // Get retrieves the details of an Xray watch by its name.

xray/manager.go Outdated
}

// GetXrayVersion will return the xray version
func (sm *XrayServicesManager) GetXrayVersion() (string, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's rename GetXrayVersion() to GetVersion(), CreateXrayWatch to CreateWatch and so on.

README.md Outdated
- [Creating an Xray Watch](#creating-an-xray-watch)
- [Get an Xray Watch](#get-an-xray-watch)
- [Update an Xray Watch](#update-an-xray-watch)
- [Delete an Xray Watch](#delete-an-xray-watch)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's also include the new version API in the README.

README.md Outdated
```go
serviceConfig, err := config.NewConfigBuilder().
SetServiceDetails(rtDetails).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rtDetails --> xrayDetails

README.md Outdated
SetCertificatesPath(certPath).
SetThreads(threads).
SetDryRun(false).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let'e remove SetThreads andSetDryRun

@josh-barker-coles
Copy link
Contributor Author

Hey @eyalbe4, thanks for the feedback. I'll start working on it this week.

@josh-barker-coles
Copy link
Contributor Author

Hi @eyalbe4, I'll fix the README conflict after we've resolved all the above discussions.

@josh-barker-coles
Copy link
Contributor Author

Hi @eyalbe4, what else is remaining for this PR?
I'd like to complete this so I can work with someone on jfrog/terraform-provider-artifactory#10

Cheers,

Josh

Copy link
Contributor

@eyalbe4 eyalbe4 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks so much for this awesome contribution @josh-barker-coles!
Please go ahead and resolve the conflict, and I'll merge this PR.

@josh-barker-coles
Copy link
Contributor Author

You're welcome @eyalbe4.

I've just rebased & resolved the README.md issue.

@eyalbe4 eyalbe4 merged commit 5bbc84f into jfrog:dev Nov 9, 2020
@yahavi
Copy link
Member

yahavi commented Feb 7, 2021

@josh-barker-coles
FYI, the APIs for Xray Watches in the Go Client are going to change in the next version - We are removing the HTTP response from the returned values.
We think that returning the HTTP response is "too low level" for such APIs. If the API failed to create the watch, an error is returned.

Before the change:

func (xws *WatchService) Delete(watchName string) (*http.Response, error)
func (xws *WatchService) Create(params utils.WatchParams) (*http.Response, error)
func (xws *WatchService) Update(params utils.WatchParams) (*http.Response, error)
func (xws *WatchService) Get(watchName string) (watchResp *utils.WatchParams, resp *http.Response, err error)

After that changes:

func (xws *WatchService) Delete(watchName string) error
func (xws *WatchService) Create(params utils.WatchParams) error
func (xws *WatchService) Update(params utils.WatchParams) error
func (xws *WatchService) Get(watchName string) (watchResp *utils.WatchParams, err error)

We hope for your understanding.

@josh-barker-coles
Copy link
Contributor Author

Hi @yahavi

Thanks for letting me know.
However, I think its worth discussing the rational behind returning the HTTP response.

Although an error indicates that something has gone wrong, it limits the ability of consumers to handle error conditions.
For example, a Internal server error (500), a Not Found (404) error, and an Unauthorized (401) error are all quite different and may require different actions.

The implication of removing the HTTP response will force consumers to write their own code to parse the string and attempt to handle the generic error.

Additionally, this design decision has wider implications for the artifactory terraform provider https://github.com/jfrog/terraform-provider-artifactory as the future goal is to refactor it to use this client library.
Yet, the 2 clients have different designs in that the old client (www.github.com/atlassian/go-artifactory) returns HTTP Responses, yet the new (jfrog-client-go) does not.

One example is https://github.com/jfrog/terraform-provider-artifactory/blob/master/pkg/artifactory/resource_artifactory_virtual_repository.go#L151-L157

Looking forward to your responses

/cc: @eyalbe4 @DarthFennec @chb0github

@eyalbe4
Copy link
Contributor

eyalbe4 commented Feb 8, 2021

Thank you for sharing this input @josh-barker-coles.
We may be able to support this requirement by attaching the HTTP response to the error returned by the APIs. We can build this mechanism in a way that it will seamlessly serve all APIs, existing and future ones.
This apparoach may require a some more thought, but I think this is doable.
Please let me know what you think.

@josh-barker-coles
Copy link
Contributor Author

Hi @eyalbe4, no worries.
Yep, I think that would be great. Do you have an implementation in mind?

It might be good to discuss with the maintainers of https://github.com/jfrog/terraform-provider-artifactory to see how that could work.

Cheers

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants