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

feat(api): Add front50-api package and move PipelineValidator into it #1035

Merged
merged 9 commits into from
Jun 11, 2021

Conversation

mochacat
Copy link
Contributor

@mochacat mochacat commented Jun 4, 2021

There isn't currently a front50-api package so I created one for the purpose of making PipelineValidator an extension point for plugin developers to utilize.

In the process of migrating this interface and limiting dependencies, I changed the Pipeline controller logic to catch a ValidationException thrown by the validator, instead of having the pipeline validator add errors to the springframework GenericValidationErrors errors. That way the front50-api doesn't need to pull in springframework just for Errors. I thought about implementing a new Errors class but it seemed like I would need to pull in even more dependencies to mimic the functionality of GenericValidationErrors.
I don't see any public implementations of the pipeline validator, but if there are any private implementations they would need to changed to throw the ValidationException instead of adding to Errors.

Pipeline and Timestamped models were also moved over from front50-core in order to limit the dependencies pulled into front50-api. I added mixin classes to front50-core so their original jackson json annotations would be respected. Pipeline was also refactored to not extend a HashMap and use explicit setters/getters.


import java.util.*;

public class Pipeline implements Timestamped {
Copy link
Contributor

Choose a reason for hiding this comment

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

Might be able to get away with Lombok in here? Pretty sure it's been used in other -api artifacts.

Copy link
Contributor

Choose a reason for hiding this comment

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

Rather than @Getter and @Setter, could probably have just added a @Data to the class?

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import java.util.Map;

@JsonIgnoreProperties(
Copy link
Contributor

Choose a reason for hiding this comment

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

Might be missing something, why are these are @JsonIgnore'd?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If you look at the deleted Pipeline file in front50-core you will see the JsonIgnore for these properties: https://github.com/spinnaker/front50/pull/1035/files/ef8c0e5ee201defe49c325902162cfdc52e4320e#r647609879

Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm ... interesting. I wonder if they were still being serialized because of the backing map.

Either way, assuming they're still being serialized it seems alright to me.

@@ -0,0 +1,53 @@
/*
* Copyright 2021 Netflix, Inc.
Copy link
Contributor

Choose a reason for hiding this comment

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

Might be worth updating your copyright, no need for it to be Netflix.

import java.util.Map;
import java.util.Set;

abstract class ForwardingMap<K, V> implements Map<K, V> {
Copy link
Contributor

Choose a reason for hiding this comment

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

Wonder if this could be eliminated with a Lombok @Delegate.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm not familiar with @Delegate but gave it a quick go without success :(

private List<Trigger> triggers = new ArrayList<Trigger>();
private Integer index;

private List<String> inherit;
Copy link
Contributor

Choose a reason for hiding this comment

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

Not sure where some of these attributes are coming from? I'm not sure I'd call many of them out as first-class attributes of a pipeline.

ie. runAsUser and serviceAccount don't make sense to me as top-level, am I missing something?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think you are right. They only belong in triggers, correct? I saw some tests with them as top-level properties, so I ended up removing them from the pipeline objects those tests.

public String getType() {
return (String) backing.get("type");
}

public void setType(String type) {
public void setType(Object type) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why did we lose the type on this? (String -> Object)

@@ -56,7 +56,7 @@ public void run() {

Predicate<Pipeline> hasExpectedGitRepoArtifact =
p -> {
List<Map> expectedArtifacts = (List<Map>) p.get("expectedArtifacts");
List<Map<String, Object>> expectedArtifacts = p.getExpectedArtifacts();
Copy link
Contributor

Choose a reason for hiding this comment

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

This migration is also seemingly past-due ... I don't think it's a good enough reason to first class expectedArtifacts.

@@ -87,7 +86,7 @@ private void migrate(Pipeline pipeline, Map<String, ServiceAccount> serviceAccou
value("pipelineId", pipeline.getId()));

Set<String> newRoles = new HashSet<>();
List<String> existingRoles = (List) pipeline.get(ROLES);
List<String> existingRoles = pipeline.getRoles();
Copy link
Contributor

Choose a reason for hiding this comment

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

Ditto here as far as first classing pipeline attributes.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I saw that SharedManagedServiceAccountsMigration needs roles so I left this pipeline attribute in.

@@ -54,7 +54,7 @@ public void run() {
log.info("Starting trigger constraint migration");
Copy link
Contributor

Choose a reason for hiding this comment

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

This is also a migration that could potentially be removed.

String schema = (String) p.getOrDefault("schema", "");
List<String> inherit = (List<String>) p.get("inherit");
List<String> exclude = (List<String>) p.get("exclude");
String schema = p.getSchema();
Copy link
Contributor

Choose a reason for hiding this comment

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

Ditto on being able to remove this migration and not first classing these attributes.

@@ -267,7 +266,11 @@ private void validatePipeline(final Pipeline pipeline, Boolean staleCheck) {
pipeline.getApplication(), pipeline.getName().trim(), pipeline.getId());

final GenericValidationErrors errors = new GenericValidationErrors(pipeline);
pipelineValidators.forEach(it -> it.validate(pipeline, errors));
try {
pipelineValidators.forEach(it -> it.validate(pipeline));
Copy link
Contributor

Choose a reason for hiding this comment

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

Slight difference in behavior wherein previously I think all validators would have run and a collection of errors would have been returned ... vs just the first failure now.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point. I ended up creating a ValidatorErrors class to store multiple errors instead of only catching the first one.

@ajordens
Copy link
Contributor

ajordens commented Jun 4, 2021

Few comments but directionally I think this is 👍

Might be worth annotating some of the new bits in front50-api with a @Beta.

return (String) super.get("application");
}

@JsonIgnore
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@ajordens leaving a comment so you can view the @JsonIgnore annotations in the original Pipeline model in front50-core.

@mochacat
Copy link
Contributor Author

mochacat commented Jun 8, 2021

@ajordens made some changes based on your comments. I switched out the ValidationException logic with for the pipeline validator with a custom validator class that can collect multiple errors.

@mochacat mochacat requested a review from ajordens June 8, 2021 17:48
Copy link
Contributor

@ajordens ajordens left a comment

Choose a reason for hiding this comment

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

This LGTM!

Thanks for the follow-up, great work.


import java.util.*;

public class Pipeline implements Timestamped {
Copy link
Contributor

Choose a reason for hiding this comment

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

Rather than @Getter and @Setter, could probably have just added a @Data to the class?

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import java.util.Map;

@JsonIgnoreProperties(
Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm ... interesting. I wonder if they were still being serialized because of the backing map.

Either way, assuming they're still being serialized it seems alright to me.

@ajordens ajordens added the ready to merge Approved and ready for merge label Jun 10, 2021
@mochacat mochacat requested a review from ajordens June 11, 2021 19:29
@mergify mergify bot merged commit 4751d87 into spinnaker:master Jun 11, 2021
@mergify mergify bot added the auto merged label Jun 11, 2021
pemmasanikrishna pushed a commit to pemmasanikrishna/front50 that referenced this pull request Sep 21, 2021
…spinnaker#1035)

* feat(api): add api package and move pipeline validator

* feat(api): move Trigger and Pipeline to api and use mixin classes for json annotations

* chore(migrations): remove out of date migrations

* refactor(api): Use lombok to generate getters/setters for Pipeline model

* feat(api): use api validator errors class for pipeline validators

* fix(api): forwarding map formatting

* fix(api): spotless apply fix

* fix(api): update sql storage service tests to use new pipleine model setters

Co-authored-by: Adam Jordens <adam@jordens.org>
dbyron-sf added a commit to dbyron-sf/front50 that referenced this pull request Apr 4, 2024
The comment in https://github.com/spinnaker/front50/pull/987/files#r515405296 is no longer
true after spinnaker#1035.  Pipeline.getTriggers no longer
makes a copy, so there's no need to get/modify/set.
mergify bot pushed a commit that referenced this pull request Apr 7, 2024
…oller.save (#1452)

* refactor(web/test): construct Pipeline objects in the first place

instead of making Maps and casting

* fix(web): restore check for regenerateCronTriggerIds in PipelineController.save

https://github.com/spinnaker/front50/pull/1035/files#diff-9b514be177faf5444c86a88ab6bb9e6a0add032bfa67862bc8e33b17c4bb9cc9L159
removed it, but orca's SavePipelineTask still sets it.

* refactor(web): adjust pipeline triggers directly

The comment in https://github.com/spinnaker/front50/pull/987/files#r515405296 is no longer
true after #1035.  Pipeline.getTriggers no longer
makes a copy, so there's no need to get/modify/set.

---------

Co-authored-by: Jason <mcintoshj@gmail.com>
dbyron-sf pushed a commit to dbyron-sf/front50 that referenced this pull request Apr 7, 2024
…ines at once to sql db.

This is part of: spinnaker/spinnaker#6147.

Enhanced PipelineController.java to

Added new rest api method bulksave(List<Map> pipelineList, Boolean staleCheck)
This method accepts a list of pipelines json.
This method checks each and every pipeline for authorization.
If the pipeline has valid authorization, then it will be saved to a savedPipelineList.
If the pipeline do not have a valid authorization, then it will be saved to a errorPipelineList
 and an error message is also populated.
All the savedPipelinesList will be saved to sql database using bulk insert.
This method returns a Map object having the below data:
{
  “Successful”: <count>,
  “Failed”: <cound>,
  “Failed_list”: [<array of failed pipelines - (application, pipeline name, etc) and the error message]
}

Enhanced AuthorizationSupport.java to

Added code to accept the pipeline list and authorize the pipelines.

Enhanced PipelineControllerSpec.java to

Added bean of FiatPermissionEvalutor.java as it is used in the PipelineController constructor.

Conflicts:
	front50-web/src/main/java/com/netflix/spinnaker/front50/controllers/PipelineController.java
	front50-web/src/test/groovy/com/netflix/spinnaker/front50/controllers/PipelineControllerSpec.groovy
	front50-web/src/test/groovy/com/netflix/spinnaker/front50/controllers/PipelineControllerTck.groovy
due to additional imports from spinnaker#1251 and spinnaker#1252

and org.springframework.context.support.DefaultMessageSourceResolvable has been removed
from master by spinnaker#1035

note, this fails to compile because bulkSave has code that expects Pipelines to behave as
Maps.  As of spinnaker#1035 that's no longer true.
dbyron-sf pushed a commit to dbyron-sf/front50 that referenced this pull request Apr 18, 2024
…ines at once to sql db.

This is part of: spinnaker/spinnaker#6147.

Enhanced PipelineController.java to

Added new rest api method bulksave(List<Map> pipelineList, Boolean staleCheck)
This method accepts a list of pipelines json.
This method checks each and every pipeline for authorization.
If the pipeline has valid authorization, then it will be saved to a savedPipelineList.
If the pipeline do not have a valid authorization, then it will be saved to a errorPipelineList
 and an error message is also populated.
All the savedPipelinesList will be saved to sql database using bulk insert.
This method returns a Map object having the below data:
{
  “Successful”: <count>,
  “Failed”: <cound>,
  “Failed_list”: [<array of failed pipelines - (application, pipeline name, etc) and the error message]
}

Enhanced AuthorizationSupport.java to

Added code to accept the pipeline list and authorize the pipelines.

Enhanced PipelineControllerSpec.java to

Added bean of FiatPermissionEvalutor.java as it is used in the PipelineController constructor.

Conflicts:
	front50-web/src/main/java/com/netflix/spinnaker/front50/controllers/PipelineController.java
	front50-web/src/test/groovy/com/netflix/spinnaker/front50/controllers/PipelineControllerSpec.groovy
	front50-web/src/test/groovy/com/netflix/spinnaker/front50/controllers/PipelineControllerTck.groovy
due to additional imports from spinnaker#1251 and spinnaker#1252

and org.springframework.context.support.DefaultMessageSourceResolvable has been removed
from master by spinnaker#1035

note, this fails to compile because bulkSave has code that expects Pipelines to behave as
Maps.  As of spinnaker#1035 that's no longer true.
dbyron-sf pushed a commit to dbyron-sf/front50 that referenced this pull request Jul 1, 2024
…ines at once to sql db.

This is part of: spinnaker/spinnaker#6147.

Enhanced PipelineController.java to

Added new rest api method bulksave(List<Map> pipelineList, Boolean staleCheck)
This method accepts a list of pipelines json.
This method checks each and every pipeline for authorization.
If the pipeline has valid authorization, then it will be saved to a savedPipelineList.
If the pipeline do not have a valid authorization, then it will be saved to a errorPipelineList
 and an error message is also populated.
All the savedPipelinesList will be saved to sql database using bulk insert.
This method returns a Map object having the below data:
{
  “Successful”: <count>,
  “Failed”: <cound>,
  “Failed_list”: [<array of failed pipelines - (application, pipeline name, etc) and the error message]
}

Enhanced AuthorizationSupport.java to

Added code to accept the pipeline list and authorize the pipelines.

Enhanced PipelineControllerSpec.java to

Added bean of FiatPermissionEvalutor.java as it is used in the PipelineController constructor.

Conflicts:
	front50-web/src/main/java/com/netflix/spinnaker/front50/controllers/PipelineController.java
	front50-web/src/test/groovy/com/netflix/spinnaker/front50/controllers/PipelineControllerSpec.groovy
	front50-web/src/test/groovy/com/netflix/spinnaker/front50/controllers/PipelineControllerTck.groovy
due to additional imports from spinnaker#1251 and spinnaker#1252

and org.springframework.context.support.DefaultMessageSourceResolvable has been removed
from master by spinnaker#1035

note, this fails to compile because bulkSave has code that expects Pipelines to behave as
Maps.  As of spinnaker#1035 that's no longer true.
dbyron-sf pushed a commit to dbyron-sf/front50 that referenced this pull request Jul 1, 2024
…ines at once to sql db.

This is part of: spinnaker/spinnaker#6147.

Enhanced PipelineController.java to

Added new rest api method bulksave(List<Map> pipelineList, Boolean staleCheck)
This method accepts a list of pipelines json.
This method checks each and every pipeline for authorization.
If the pipeline has valid authorization, then it will be saved to a savedPipelineList.
If the pipeline do not have a valid authorization, then it will be saved to a errorPipelineList
 and an error message is also populated.
All the savedPipelinesList will be saved to sql database using bulk insert.
This method returns a Map object having the below data:
{
  “Successful”: <count>,
  “Failed”: <cound>,
  “Failed_list”: [<array of failed pipelines - (application, pipeline name, etc) and the error message]
}

Enhanced AuthorizationSupport.java to

Added code to accept the pipeline list and authorize the pipelines.

Enhanced PipelineControllerSpec.java to

Added bean of FiatPermissionEvalutor.java as it is used in the PipelineController constructor.

Conflicts:
	front50-web/src/main/java/com/netflix/spinnaker/front50/controllers/PipelineController.java
	front50-web/src/test/groovy/com/netflix/spinnaker/front50/controllers/PipelineControllerSpec.groovy
	front50-web/src/test/groovy/com/netflix/spinnaker/front50/controllers/PipelineControllerTck.groovy
due to additional imports from spinnaker#1251 and spinnaker#1252

and org.springframework.context.support.DefaultMessageSourceResolvable has been removed
from master by spinnaker#1035

note, this fails to compile because bulkSave has code that expects Pipelines to behave as
Maps.  As of spinnaker#1035 that's no longer true.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
4 participants