-
Notifications
You must be signed in to change notification settings - Fork 55
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
REST API for accessing adjuncts (including highlights) #821
REST API for accessing adjuncts (including highlights) #821
Conversation
07247e8
to
45261c7
Compare
Big changes to config key construction, following on from previous deprecation
4a148f9
to
83c3d50
Compare
rebased to incorporate deprecation around the multiple config REST classes and add a tidy API for that |
@ahgittin The description says |
@tbouron It's up to date. Primarily it is still just the one commit adding the Adjunct API -- it does have a lot of lines but they are mostly boilerplate (like a couple hundred just to declare the API) ... REST cruft and annotations. However the merge of the |
Cool, thanks @ahgittin. I'm reviewing it right now. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @ahgittin for the PR. There are few minor comments but most importantly, I tested it and found 2 interesting things:
- If you run in karaf mode (which is the default now) the new endpoint is not available! It's not the case for classic though.
- on the swagger page, it is never mentioned that the entire
Entity Policy
andEntity Policy Config
are deprecated.
@@ -43,7 +43,7 @@ | |||
|
|||
/** | |||
* True if everything has been _started_ (or it is starting) but not stopped, | |||
* even if it is suspended; see also {@link #isActive()} | |||
* even if it is suspended; see also {@link #isRunning()} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Neither of isRunning
or isActive
methods are available in the class. Did you want to link to somewhere else?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isRunning
is inherited from EntityAdjunct
, so I think this javadoc link is ok.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isRunning()
is avail, inherited from EntityAdjunct
@@ -189,7 +189,7 @@ | |||
void remove(AttributeSensor<?> attribute); | |||
} | |||
|
|||
public interface FeedSupport { | |||
public interface FeedSupport extends Iterable<Feed> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it really necessary to extend from Iterable
and have an iterator()
method here where we can get it from the getFeed().iterator()
method (which always returns a collection) ? I don't see the benefit of creating this small shortcut
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding this gives consistency with entity's enrichers()
and policies()
which both return something that implements Iterable<T>
. I therefore think it's a good idea.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is to bring it in line with other AdjunctSupport
classes. have made more steps in this direction in a new commit.
return Lifecycle.CREATED; | ||
} | ||
|
||
return Lifecycle.STOPPED; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What other adjunct should it be to arrive here? Enrichers? In this case, is an enricher really STOPPED
instead of CREATED
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you are right, changed
} | ||
|
||
@Beta | ||
public static Lifecycle inferAdjunctStatus(EntityAdjunct a) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds like this method is not in a right class. Would be more meaningful inside an Adjuncts
class for example (an since it's static, it is not an issue to move it)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would also deprecate the entire Policies
class as all methods are already deprecated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good spot. moved to EntityAdjuncts
and deprecated this class, removing previously deprecated methods
@ApiParam(value = "Entity ID or name", required = true) | ||
@PathParam("entity") final String entityToken, | ||
@ApiParam(value = "Filter by adjunct type", required = false) | ||
@QueryParam("adjunctType") final String adjunctType); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
type
would be better here as we already have the context, i.e. we are looking at a specific type for an adjunct. But no strong feelings. It will also be consistent with the POST
operation below
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wondered about type
as well. Problem is we don't support filtering by the actual type (e.g. if someone is looking for AutoScalerPolicy
only). It's a very similar discussion to the subtype/supertype/category discussion for PR https://github.com/apache/brooklyn-server/pull/810/files#diff-53a117c93b2d8af2b0b2198599c0c6d1. I think we should follow the same naming here as we do there - i.e. supertype
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no, the POST takes a specific registered type, whereas this is essentially the adjunct kind; have improved comments to make clear. would adjunctKind
be a better name? or supertype
for consistency with /catalog/types
?
EntityAdjunct adjunct = brooklyn().getAdjunct(application, entityToken, adjunctId); | ||
if (adjunct instanceof Policy) ((Policy)adjunct).resume(); | ||
else if (adjunct instanceof Feed) ((Feed)adjunct).resume(); | ||
else throw WebResourceUtils.badRequest("%s does not support start/resume", adjunct); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think enrichers should support suspend/resume? If so, worth adding a TODO here.
EntityAdjunct adjunct = brooklyn().getAdjunct(application, entityToken, adjunctId); | ||
if (adjunct instanceof Policy) ((Policy)adjunct).suspend(); | ||
else if (adjunct instanceof Feed) ((Feed)adjunct).suspend(); | ||
else throw WebResourceUtils.badRequest("%s does not support suspend", adjunct); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above
return Response.status(Response.Status.OK).build(); | ||
} | ||
|
||
public static String getStringValueForDisplay(BrooklynRestResourceUtils utils, EntityAdjunct policy, Object value) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method is unused, can be deleted
@@ -71,6 +71,8 @@ | |||
import com.google.common.collect.ImmutableSet; | |||
import com.google.common.collect.Sets; | |||
|
|||
/** @deprecated since 0.13.0 use RegisteredType methods */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing Javadoc link for RegisteredType
} | ||
for (Feed p: ((EntityInternal)entity).feeds()) { | ||
if (adjunct.equals(p.getDisplayName())) return p; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can group the loops of the same type, that would reduce in half the processing time
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Depends whether we worry about a display name being the same as an id anywhere - and thus what guarantees we're trying to give.
I probably agree @tbouron. If we do want to keep them separate, we should iterate over all ids (policies, enrichers, feeds) before going on to display names.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no - in perverse case where we have feed<ID=1 name=2> and feed<ID=2 name=foo> a call to get "2" should return the latter, whereas combining loops would return the former
we do need to compare all by ID's first however
agree it's an edge case and isn't significant but think the code should stay with separate loops.
PS processing time change would not be as large as you say as the string comparison dominates execution time and that is unchanged by combining loops.
BTW, I just realised that there is no tests coverage for the new endpoints |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM - only minor comments.
AbstractBrooklynObjectSpec<?, ?> spec; | ||
if (rt!=null) { | ||
spec = brooklyn().getTypeRegistry().createSpec(rt, null, null); | ||
} else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(I see this code is taken from PolicyResource.addPolicy
, and has been approved - therefore no strong feelings for this PR.)
Do we really need the fallback to java, or can we assume that it must be in the catalog? (we don't even support feeds, which aren't in the catalog yet).
Ideally I'd like us to not have to support this code path, or to have a deprecation warning logged in that else branch (telling people to add it to the catalog).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i'd like to switch to yaml for this, have added comment
@ApiResponse(code = 404, message = "Could not find application or entity"), | ||
@ApiResponse(code = 400, message = "Type is not a suitable adjunct") | ||
}) | ||
public AdjunctSummary addAdjunct( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I compared the EntityApi.addChildren
to this. It would be really nice if one could just pass in YAML for the adjunct being added (similar to addChildren
).
How feasible would that be? I'm guessing our yaml parser just doesn't have the right entry points for that.
Perhaps we should mark this as @Beta
(including in the swagger description text, and come back to it in a v2?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
have added comment about supporting yaml. this isn't an addition, it's just a migration, so i wouldn't deprecate until we have the yaml parser for it. (with yoml it should be easy to plug in to the right place. not too hard even so.)
* | ||
* @throws 404 or 412 (unless input is null in which case output is null) */ | ||
public EntityAdjunct getAdjunct(Entity entity, String adjunct) { | ||
if (adjunct==null) return null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Feels wrong to return null if the adjunct
param is null.
Looking at the uses of it, that results in a subsequent NPE (i.e. a 500 response code).
I'd change this method to return an appropriate 4xx response code (not sure which one - writing this offline!)
I know that in this PR you've just followed the same convention as for getPolicy()
, getEntity()
, etc. But I think they are wrong as well! Happy for us to do that in a different PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's make it separate just in case -- agree no use case for null
input. i'd probably make it a fail-fast NPE (500 or 412 precondition failed) rather than a 404.
EntityAdjunct adjunct = brooklyn().getAdjunct(application, entityToken, adjunctId); | ||
if (adjunct instanceof Policy) ((Policy)adjunct).resume(); | ||
else if (adjunct instanceof Feed) ((Feed)adjunct).resume(); | ||
else throw WebResourceUtils.badRequest("%s does not support start/resume", adjunct); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think enrichers should support suspend/resume? If so, worth adding a TODO here.
return result; | ||
} | ||
|
||
// TODO support parameters ?show=value,summary&name=xxx &format={string,json,xml} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd move that comment to the AdjunctsApi
interface, rather than in the impl (given it's about the api rather than the implementation).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
already there
public String getConfig(String application, String entityToken, String adjunctToken, String configKeyName) { | ||
EntityAdjunct adjunct = brooklyn().getAdjunct(application, entityToken, adjunctToken); | ||
Set<ConfigKey<?>> cki = adjunct.config().findKeysDeclared(ConfigPredicates.nameSatisfies(Predicates.equalTo(configKeyName))); | ||
if (cki.isEmpty()) throw WebResourceUtils.notFound("Cannot find config key '%s' in policy '%s' of entity '%s'", configKeyName, adjunctToken, entityToken); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be "in adjunct ", rather than "in policy ".
|
||
EntityAdjunct adjunct = brooklyn().getAdjunct(entity, adjunctToken); | ||
Set<ConfigKey<?>> cki = adjunct.config().findKeysDeclared(ConfigPredicates.nameSatisfies(Predicates.equalTo(configKeyName))); | ||
if (cki.isEmpty()) throw WebResourceUtils.notFound("Cannot find config key '%s' in policy '%s' of entity '%s'", configKeyName, adjunctToken, entityToken); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be "in adjunct ", rather than "in policy ".
public ConfigSummary transform() { | ||
MutableMap.Builder<String, URI> lb = new MutableMap.Builder<String, URI>(); | ||
|
||
if (ub!=null && entity!=null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Feels like a programming error if someone called includeLinks
(to supply a UriBuilder
), but the entity
is null. Perhaps fail-fast rather than just missing out the links? Otherwise our unit tests may well all pass if such a programming error is introduced.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there might be a context where someone wants to include whatever links are possible but an entity may or may not be present. i wouldn't say it's necessarily a programming error. if inclusion in links is wanted unit tests should check it explicitly rather than constrain this method to fail-fast.
i'll update javadoc on includeLinks
methods
@@ -36,6 +36,8 @@ | |||
@Api("Entity Policies") | |||
@Produces(MediaType.APPLICATION_JSON) | |||
@Consumes(MediaType.APPLICATION_JSON) | |||
/** @deprecated since 0.12.0 use AdjunctApi */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this be "since 0.13.0"?
(Please search https://github.com/apache/brooklyn-server/pull/821/files for that text)
} | ||
for (Feed p: ((EntityInternal)entity).feeds()) { | ||
if (adjunct.equals(p.getDisplayName())) return p; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Depends whether we worry about a display name being the same as an id anywhere - and thus what guarantees we're trying to give.
I probably agree @tbouron. If we do want to keep them separate, we should iterate over all ids (policies, enrichers, feeds) before going on to display names.
…lasses deprecating more methods which need to change or should go will need to add FeedSpec in future to bring it fully in line
…date other deprecated
e2c3f4c
to
28dbb83
Compare
one question from above to call out special @tbouron (given how github hides things) regarding the
you've suggested |
left it as tests added that's everything addresses i think |
@ahgittin Sorry, I did miss your comment. I was suggesting type to be consistent with the |
NB: builds on #810 and #818, review and merge those first
This is then just one commit (currently) which:
AdjunctApi
combining all the functionality ofPolicyApi
andPolicyConfigApi
generalized across adjunct typesAdjunctConfigSummary
CatalogApi
/catalog
endpoint (since we are deprecating; also there is some overlap atCatalogPolicyItem
andPolicyConfigSummary
etc)This is mostly a drop-in replacement for the
/applications/XXX/entities/XXX/policies/*
endpoints, now using/applications/XXX/entities/XXX/adjuncts/*
and returning other items. Note also that:GET /v1/applications/XXX/entities/XXX/adjuncts?adjunctType=policy
filters by policy (same for other types)adjunctType
is included in the returned objectGET /v1/applications/XXX/entities/XXX/adjuncts/XXX
includes more info (config keys aka parameters, and values)links
on the detail object include links tostart
andstop
if and only if the adjunct supports that; it is recommended that clients use this value or at least check its presence rather than assume the declared.../start
and.../stop
endpoints will always be supported, as some adjuncts don't support (such as enrichers ... though we could and might change that ... so doing this check will be future-proof)