How do I execute a custom ResourceInitializer - moryx

I followed the instructions in the Template repository to create the Resources database. But now I want to use a custom ResourceInitializer to add Resources to the ResourceGraph. (see my code below)
namespace MyApplication.Resources.MyResource
{
[ResourceInitializer(nameof(DummyInitializer))]
public class DummyInitializer : ResourceInitializerBase
{
...
}
}
But when I go into the runtime console and execute exec ResourceManager initialize, the initializer is not shown in the list:
Output in the runtime window
How do I get the runtime to show me the DummyInitializer?

The Initializers you see in the console, are the ones configured in the resource managers initializer collection. In the MaintenanceWeb you can add an entry for your initializer under: http://localhost/maintenanceweb/#/modules/ResourceManager/configuration?path=ModuleConfig/Initializers
or you can add it the underlying config file.
{
"Initializers": [
{
"PluginName": "DummyInitializer"
}
]
}
Alternatively you can execute it using the resource managers console at: http://localhost/maintenanceweb/#/modules/ResourceManager/console
I hope that helps, let me know if you need further help.

Related

How do I programmatically stop a teamcity build agent instance after current build?

On Teamcity, when I click an agent, I get the "Agent Summary", "Build History", "Compatible Configurations", etc. etc. I can also see the running build and the "Miscellaneous" section, like this one:
I would like to know how I can run the "Stop instance after current build" with the Teamcity API. Does that correspond to deleting the agent or is there something else?
If you want to do it from the build itself, then you can emulate the HTTP request that UI sends when a user clicks the "Stop instance after current build" button
The best way I was advised to follow in order to solve my issue is to define a cloud profile which terminates agents after the first build. To achieve that, in my teamcity project, I have defined (in kotlin DSL):
project {
[...]
features {
feature(ProjectFeature({
type = "CloudProfile"
id = "stop_instance_after_current_build"
// various cloud profile parameters, like
// profileServerUrl, secure:access-id, total-work-time, etc.
// which you find by GETting <teamcity-url>/app/rest/projects/id:<project-id>/projectFeatures/
[...]
// there should be no terminate-idle-time parameter
param("terminate-after-build", true.toString())
})
}
}
With that in place, in a build configuration associated to that project, I do
class SomeBuildConfig() : BuildType({
[...]
requirements {
equals("system.cloud.profile_id", "stop_instance_after_current_build")
}
})
If we don't want to rely on %system.cloud.profile_id%, it is also possible to define a dedicated variable in the agent through the user-script parameter of a ProjectFeature of CloudImage type:
project {
[...]
features {
feature(ProjectFeature({
type = "CloudProfile"
id = "stop_instance_after_current_build"
// as above
[...]
})
feature(ProjectFeature({
type = "CloudImage"
// various parameters like e.g. image-name-prefix, key-pair-name, subnet-id, amazon-id, etc.
[...]
param("profileId", "stop_instance_after_current_build")
param("user-script", userData)
})
}
}
where userData is the content of a script like this:
#! /bin/sh
echo "teamcity.agent.killed_after_current_build=true" >> /home/ubuntu/buildAgent/conf/buildAgent.properties
Then, in a build configuration associated to that project, we can do
requirements {
equals("teamcity.agent.killed_after_current_build", "true")
}

Configuring a custom Gradle sourceSet using a closure

I'm trying to develop a Gradle plugin for a language I use (SystemVerilog). I'm still experimenting and figuring things out. Before I write the entire thing as a plugin, I thought it would be best to try out the different parts I need inside a build script, to get a feel of how things should work.
I'm trying to define a container of source sets, similar to how the Java plugin does it. I'd like to be able to use a closure when configuring a source set. Concretely, I'd like to be able to do the following:
sourceSets {
main {
sv {
include '*.sv'
}
}
}
I defined my own sourceSet class:
class SourceSet implements Named {
final String name
final ObjectFactory objectFactory
#Inject
SourceSet(String name, ObjectFactory objectFactory) {
this.name = name
this.objectFactory = objectFactory
}
SourceDirectorySet getSv() {
SourceDirectorySet sv = objectFactory.sourceDirectorySet('sv',
'SystemVerilog source')
sv.srcDir("src/${name}/sv")
return sv
}
SourceDirectorySet sv(#Nullable Closure configureClosure) {
configure(configureClosure, getSv());
return this;
}
}
I'm using org.gradle.api.file.SourceDirectorySet because that already implements PatternFilterable, so it should give me access to include, exclude, etc.
If I understand the concept correctly, the sv(#Nullable Closure configureClosure) method is the one that gives me the ability to write sv { ... } to configure via a closure.
To add the sourceSets property to the project, I did the following:
project.extensions.add("sourceSets",
project.objects.domainObjectContainer(SourceSet.class))
As per the Gradle docs, this should give me the possibility to configure sourceSets using a closure. This site, which details using custom types, states that by using NamedDomainObjectContainer, Gradle will provide a DSL that build scripts can use to define and configure elements. This would be the sourceSets { ... } part. This should also be the sourceSets { main { ... } } part.
If I create a sourceSet for main and use it in a task, then everything works fine:
project.sourceSets.create('main')
task compile(type: Task) {
println 'Compiling source files'
println project.sourceSets.main.sv.files
}
If I try to configure the main source set to only include files with the .sv extension, then I get an error:
sourceSets {
main {
sv {
include '*.sv'
}
}
}
I get the following error:
No signature of method: build_47mnuak4y5k86udjcp7v5dkwm.sourceSets() is applicable for argument types: (build_47mnuak4y5k86udjcp7v5dkwm$_run_closure1) values: [build_47mnuak4y5k86udjcp7v5dkwm$_run_closure1#effb286]
I don't know what I'm doing wrong. I'm sure it's just a simple thing that I'm forgetting. Does anyone have an idea of what that might be?
I figured out what was going wrong. It was a combination of poor copy/paste skills and the fact that Groovy is a dynamic language.
First, let's look at the definition of the sv(Closure) function again:
SourceDirectorySet sv(#Nullable Closure configureClosure) {
configure(configureClosure, getSv());
return this;
}
Once I moved this code to an own Groovy file and used the IDE to show me what is getting called, I noticed that it wasn't calling the function I expected. I was expecting a call to org.gradle.util.ConfigureUtil.configure. Since this is part of the public API, I expected it to be imported by default in the build script. As this page states, this is not the case.
To solve the issue, it's enough to add the following import:
import static org.gradle.util.ConfigureUtil.configure
This will get rid of the cryptic closure related error. It is replaced by the following error, though:
Cannot cast object 'SourceSet_Decorated#a6abab9' with class 'SourceSet_Decorated' to class 'org.gradle.api.file.SourceDirectorySet'
This is caused by the copy/paste error I mentioned. When I wrote the SourceSet class, I drew heavily from org.gradle.api.tasks.SourceSet (and org.gradle.api.internal.tasks.DefaultSourceSet). If we look at the java(Closure) method there, we'll see it has the following signature:
SourceSet java(#Nullable Closure configureClosure);
Notice that it returns SourceSet and not SourceDirectorySet like in my code. Using the proper return type fixes the issue:
SourceSet sv(#Nullable Closure configureClosure)
With this new return type, let's look again at the configuration code for the source set:
sourceSets {
main {
sv {
include '*.sv'
}
}
}
Initially, I thought it was supposed to work as follows: pass main { ... } as a Closure to sourceSets, pass sv { ... } as a Closure to main, and handle the include ... part inside sourceDirectorySet. I banged my head against the wall for a while, because I couldn't find any code in that class hierarchy that takes closures like this.
Now, I think the flow is slightly different: pass main { ... } as a Closure to sourceSets (as initially thought), but call the sv(Closure) function on main (of type sourceSet), passing it { include ... } as the argument.
Bonus: There was one more issue that wasn't related to the "compile" errors I was having.
Even after getting the code to run without errors, it still wasn't behaving as expected. I had some files with the *.svh extension that were still getting picked up. This is because, when calling getSv(), it was creating a new SourceDirectorySet each time. Any configuration that was done previously was getting thrown away each time that this function was called.
Making the sourceDirectorySet a class member and moving its creation to the constructor fixed the issue:
private SourceDirectorySet sv
SourceSet(String name, ObjectFactory objectFactory) {
// ...
sv = objectFactory.sourceDirectorySet('sv',
'SystemVerilog source')
sv.srcDir("src/${name}/sv")
}
SourceDirectorySet getSv() {
return sv
}

Run Time Error: perhaps its code was not linked in, or the class wasn't registered with Register_Class()/Define_Module()/Define_Channel()?

I have already declared Define_Module(veins:: TraCIDateDissemination) and go through with various suggestions provided but getting this error again. Any suggestion is welcome. please help.
How to register a new class (new application) in Omnet++
Error in module during network setup:
Class "simpleModule" not found in omnetpp
https://doc.omnetpp.org/omnetpp/manual/
In manual I checked -
7.12.3 Class Registration
You should also use the Register_Class() macro to register the new class. It is used by the createOne() factory function, which can create any object given the class name as a string. createOne() is used by the Envir library to implement omnetpp.ini options such as rng-class="..." or scheduler-class="...". (see Chapter [17])
But not able to understand. pls help.
A runtime error occurred:
Class "TraCIDataDissemination" not found -- perhaps its code was not linked in, or the class wasn't registered with Register_Class(), or in the case of modules and channels, with Define_Module()/Define_Channel() -- in module (omnetpp::cModule) RSUExampleScenario.node[0] (id=13), at t=1s, event #2
Launch a debugger with the following command?
nemiver --attach=20070 &
OMNET.INI
##########################################################
# App Layer #
##########################################################
#*.node[*].applType = "TraCIDemo11p"
*.node[*].applType = "TraCIDataDissemination"
*.node[*].appl.headerLength = 80 bit
TraCIDataDissemination.h
namespace veins {
class TraCIDataDissemination : public DemoBaseApplLayer {
public:
{
//my code
}
}
TraCIDataDissemination.cc
#include "veins/modules/application/traci/TraCIDataDissemination.h"
#include<math.h>
using namespace veins;
Define_Module(veins::TraCIDataDissemination);
//code
TraCIDataDissemination.ned
package org.car2x.veins.modules.application.traci;
import org.car2x.veins.modules.application.ieee80211p.DemoBaseApplLayer;
simple TraCIDataDissemination extends DemoBaseApplLayer
{
#class(TraCIDataDissemination);
#display("i=block/app2");
}
Please Help!!

EventFlow - Creating a Custom Filter to attach Source Server Information

I'm assuming this is a pretty common question, how do we easily add Server info to an EventFlow event?
My scenario is that I'm deploying an application that will have its own environment specific EventFlowConfig.json, but each server in the farm will get that same json file. So... how can I tell which server in the farm sent the event to ElasticSearch?
One option is to use .net to get servername and send it as a column, which would require that I add server name to every event. That seems a little excessive but it would do the job. I was hoping there was an easier way besides having to actually code this into an event.
Thanks for your time,
Greg
Edit 4 - Karol has been great helping me get this working example up and running, THANK YOU KAROL!!! Attempting to add create a custom filter as an extension:
We need to create a new class for the custom Filter Factory
We then need to create a second new class and have it implement the IFilter interface. To pass the health monitor from the factory we used a constructor.
Use the Evaluate function as our area to add the data (eventData.AddPayloadProperty)
Then refer to the custom filter in the extensions area of our EventFlowConfig.json.
a. The category is filterFactory
b. The type is the name of your class.
c. The qualified type name is in the "type-name, assembly-name”. For example (assuming you name your filter factory ‘MyCustomFilterFactory’): “My.Application.Logging.MyCustomFilterFactory, My.Application.Assembly.WhereCustomFilterAndItsFactoreLive”
Add a reference to Microsoft.Extensions.Configuration where the C# code lives.
Then you can reference your custom filter anywhere you need to, here we are using a global filter
Working example:
class CustomGlobalFilter : IFilter
{
private IHealthReporter HealthReporter;
private string MachineName;
public CustomGlobalFilter(string ServerName, IHealthReporter HealthReporter)
{
MachineName = ServerName;
this.HealthReporter = HealthReporter;
}
FilterResult IFilter.Evaluate(EventData eventData)
{
eventData.AddPayloadProperty("ServerName", MachineName, HealthReporter, "CustomGlobalFilter");
return FilterResult.KeepEvent;
}
}
class CustomGlobalFilterFactory : IPipelineItemFactory<CustomGlobalFilter>
{
public CustomGlobalFilter CreateItem(IConfiguration configuration, IHealthReporter healthReporter)
{
CustomGlobalFilter GlobalFilter = new CustomGlobalFilter(System.Environment.MachineName, healthReporter);
return GlobalFilter;
}
}
Then in the EventFlow Config:
"filters": [
{
"type": "drop",
"include": "Level == Verbose"
},
{
"type": "CustomGlobalFilter"
}
],
...
"extensions": [
{
"category": "filterFactory",
"type": "CustomGlobalFilter",
"qualifiedTypeName": "My.Company.Presentation.App.CustomGlobalFilter, My.Company.Presentation.App"
}
It is not something that is built into EventFlow today, but there are at least a couple of options:
Use EventFlow extensibility to add a custom filter that adds these properties to every event it “sees”.
In many logging libraries there is a concept of “initializers” or “enrichment” that can be used to automatically add contextual properties. For example in Serilog (which is natively supported by EventFlow)

Gradle extension as NamedDomainObjectContainer of Closure

I'm trying to build a Gradle plugin that would allow the following:
myPluginConfig {
something1 {
// this is a closure
}
somethingElse {
// this is another closure
}
// more closures here
}
To achieve this I'm fairly certain I need to use a NamedDomainObjectContainer to wrap a Closure collection, so I've set up the following plugin:
class SwitchDependenciesPlugin implements Plugin<Project> {
void apply(Project project) {
// add the extension
project.getExtensions().myPluginConfig = project.container(Closure)
// read the current configuration
NamedDomainObjectContainer<Closure> config = project.myPluginConfig
// test it out, always returns []
System.out.println(config)
}
}
What am I doing wrong, do I need to use project.extensions.create instead? If so, how?
EDIT: my use case consists in adding dependencies according to some variables defined in the project hierarchy. For example, the following configuration would add the red project if the variable red is defined on project.ext, or gson otherwise:
myPluginConfig {
redTrue {
compile project(':red')
}
redFalse {
compile 'com.google.code.gson:gson:2.4'
}
greenTrue {
compile project(':green')
}
}
For this use case I need to have dynamic names for myPluginConfig, and therefore either a Map or a NamedDomainObjectContainer.
Can you elaborate what you try to model here? I think you have two options. One is to use NamedDomainObjectContainer. Here you need a class that represents "something". Have a look at the Gradle userguide chapter about maintaining multiple domain objects (see https://docs.gradle.org/current/userguide/custom_plugins.html#N175CF) in the sample of the userguide, the "thing" is 'Book'. The build-in configuration syntax like you described above comes for free.
If you want to have a syntax like above without the need for maintaining multiple domain objects, you can simply add a method that takes a Closure as a parameter to your Extension class:
void somethingToConfigure(Closure) {
}
You cannot have Closure as a type for NamedDomainObjectContainer simply because the type you use must have a property called name and a public constructor with a single String parameter.
To overcome this, you may create a wrapper around Closure with a name field added.

Resources