From b0455b141643f18d5025e23ac7859da43afe7f19 Mon Sep 17 00:00:00 2001 From: "adheli.tavares" Date: Fri, 12 Jan 2024 16:16:40 +0000 Subject: Fix topic lower case for kafka compability Issue-ID: POLICY-4402 Change-Id: I0598bc83b5f4d46c79d7c5c897fd1e6e253b9238 Signed-off-by: adheli.tavares --- .../controller/usecases/UsecasesEventManager.java | 3 ++ .../src/main/resources/usecases.drl | 24 +++++----- .../org/onap/policy/controlloop/UsecasesTest.java | 2 +- .../test/resources/config/event-manager.properties | 20 ++++---- .../config/usecases-controller.properties | 55 +++++++++++----------- .../controlloop/common/rules/test/BaseTest.java | 23 +++++---- .../controlloop/common/rules/test/Rules.java | 7 +-- 7 files changed, 67 insertions(+), 67 deletions(-) (limited to 'controlloop/common') diff --git a/controlloop/common/controller-usecases/src/main/java/org/onap/policy/drools/apps/controller/usecases/UsecasesEventManager.java b/controlloop/common/controller-usecases/src/main/java/org/onap/policy/drools/apps/controller/usecases/UsecasesEventManager.java index 8d09b1c40..86a189dd3 100644 --- a/controlloop/common/controller-usecases/src/main/java/org/onap/policy/drools/apps/controller/usecases/UsecasesEventManager.java +++ b/controlloop/common/controller-usecases/src/main/java/org/onap/policy/drools/apps/controller/usecases/UsecasesEventManager.java @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2020-2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,6 +37,7 @@ import static org.onap.policy.drools.apps.controller.usecases.UsecasesConstants. import static org.onap.policy.drools.apps.controller.usecases.UsecasesConstants.VSERVER_PROV_STATUS; import static org.onap.policy.drools.apps.controller.usecases.UsecasesConstants.VSERVER_VSERVER_NAME; +import java.io.Serial; import java.util.Deque; import java.util.Map; import java.util.Set; @@ -70,6 +72,7 @@ import org.onap.policy.sdnr.PciMessage; */ public class UsecasesEventManager extends ClEventManagerWithEvent implements StepContext { + @Serial private static final long serialVersionUID = -1216568161322872641L; /** diff --git a/controlloop/common/controller-usecases/src/main/resources/usecases.drl b/controlloop/common/controller-usecases/src/main/resources/usecases.drl index c10b8d0c9..14bc9a406 100644 --- a/controlloop/common/controller-usecases/src/main/resources/usecases.drl +++ b/controlloop/common/controller-usecases/src/main/resources/usecases.drl @@ -3,7 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2020-2022 AT&T Intellectual Property. All rights reserved. - * Modifications Copyright (C) 2023 Nordix Foundation. + * Modifications Copyright (C) 2023-2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -210,7 +210,7 @@ rule "EVENT" // try { if (notification != null) { - PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification); + PolicyEngineConstants.getManager().deliver("policy-cl-mgt", notification); } } catch(RuntimeException e) { @@ -382,7 +382,7 @@ rule "EVENT.MANAGER.ACCEPT" notification.setPolicyScope(drools.getRule().getName()); notification.setPolicyName($manager.getPolicyName()); notification.setPolicyVersion($manager.getPolicyVersion()); - $manager.deliver("POLICY-CL-MGT", notification, "notification", drools.getRule().getName()); + $manager.deliver("policy-cl-mgt", notification, "notification", drools.getRule().getName()); } catch(RuntimeException e) { logger.warn("{}: {}.{}: manager={} exception processing operation outcome", @@ -478,7 +478,7 @@ rule "EVENT.MANAGER.GENERATE.SDNR.NOTIFICATION" try { ControlLoopResponse clResponse = $manager.makeControlLoopResponse($outcome); - $manager.deliver("DCAE_CL_RSP", clResponse, "SDNR notification", drools.getRule().getName()); + $manager.deliver("dcae_cl_rsp", clResponse, "SDNR notification", drools.getRule().getName()); } catch(RuntimeException e) { logger.warn("{}: {}.{}: manager={} exception generating SDNR Response notification", @@ -536,7 +536,7 @@ rule "EVENT.MANAGER.PROCESS.GUARD.OUTCOME" + " is Deny"); } - $manager.deliver("POLICY-CL-MGT", notification, "GUARD notification", drools.getRule().getName()); + $manager.deliver("policy-cl-mgt", notification, "GUARD notification", drools.getRule().getName()); } catch(RuntimeException e) { logger.warn("{}: {}.{}: manager={} exception generating GUARD notification", @@ -585,7 +585,7 @@ rule "EVENT.MANAGER.PROCESS.POLICY.STARTED" notification.setHistory(Collections.emptyList()); notification.setMessage($manager.getOperationMessage()); - $manager.deliver("POLICY-CL-MGT", notification, "notification", drools.getRule().getName()); + $manager.deliver("policy-cl-mgt", notification, "notification", drools.getRule().getName()); } catch(RuntimeException e) { logger.warn("{}: {}.{}: manager={} exception processing operation outcome", @@ -684,7 +684,7 @@ rule "EVENT.MANAGER.PROCESS.POLICY.SUCCESS" $manager.setState(State.POLICY_LOADED); - $manager.deliver("POLICY-CL-MGT", notification, "notification", drools.getRule().getName()); + $manager.deliver("policy-cl-mgt", notification, "notification", drools.getRule().getName()); } catch(RuntimeException e) { logger.warn("{}: {}.{}: manager={} exception processing operation outcome", @@ -747,7 +747,7 @@ rule "EVENT.MANAGER.PROCESS.FINAL.FAILURE.ACCEPTED" $manager.getSteps().clear(); $manager.setState(State.POLICY_LOADED); - $manager.deliver("POLICY-CL-MGT", notification, "notification", drools.getRule().getName()); + $manager.deliver("policy-cl-mgt", notification, "notification", drools.getRule().getName()); } catch(RuntimeException e) { logger.warn("{}: {}.{}: manager={} exception processing operation outcome", @@ -802,7 +802,7 @@ rule "EVENT.MANAGER.PROCESS.FINAL.FAILURE.REJECTED" notification.setHistory($manager.getPartialHistory().stream().map(OperationOutcome2::getClOperation) .toList()); - $manager.deliver("POLICY-CL-MGT", notification, "notification", drools.getRule().getName()); + $manager.deliver("policy-cl-mgt", notification, "notification", drools.getRule().getName()); } catch(RuntimeException e) { logger.warn("{}: {}.{}: manager={} exception processing operation outcome", @@ -856,7 +856,7 @@ rule "EVENT.MANAGER.PROCESS.POLICY.FAILURE" notification.setPolicyName($manager.getPolicyName()); notification.setPolicyVersion($manager.getPolicyVersion()); - $manager.deliver("POLICY-CL-MGT", notification, "notification", drools.getRule().getName()); + $manager.deliver("policy-cl-mgt", notification, "notification", drools.getRule().getName()); } catch(RuntimeException e) { logger.warn("{}: {}.{}: manager={} exception processing operation outcome", @@ -959,7 +959,7 @@ rule "EVENT.MANAGER.ABORT" // aborted while processing the SDNR step - generate a notification ControlLoopResponse clResponse = $manager.makeControlLoopResponse($outcome); - $manager.deliver("DCAE_CL_RSP", clResponse, "SDNR notification", drools.getRule().getName()); + $manager.deliver("dcae_cl_rsp", clResponse, "SDNR notification", drools.getRule().getName()); } if ($step != null) { @@ -1032,7 +1032,7 @@ rule "EVENT.MANAGER.FINAL" notification.setMessage($manager.getFinalMessage()); } - $manager.deliver("POLICY-CL-MGT", notification, "notification", drools.getRule().getName()); + $manager.deliver("policy-cl-mgt", notification, "notification", drools.getRule().getName()); } catch(RuntimeException e) { logger.warn("{}: {}.{}: manager={} exception generating final notification", diff --git a/controlloop/common/controller-usecases/src/test/java/org/onap/policy/controlloop/UsecasesTest.java b/controlloop/common/controller-usecases/src/test/java/org/onap/policy/controlloop/UsecasesTest.java index 625a1a0f1..6674680cd 100644 --- a/controlloop/common/controller-usecases/src/test/java/org/onap/policy/controlloop/UsecasesTest.java +++ b/controlloop/common/controller-usecases/src/test/java/org/onap/policy/controlloop/UsecasesTest.java @@ -3,7 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2020-2022 AT&T Intellectual Property. All rights reserved. - * Modifications Copyright (C) 2023 Nordix Foundation. + * Modifications Copyright (C) 2023-2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/controlloop/common/controller-usecases/src/test/resources/config/event-manager.properties b/controlloop/common/controller-usecases/src/test/resources/config/event-manager.properties index ad5599142..8ca428a2d 100644 --- a/controlloop/common/controller-usecases/src/test/resources/config/event-manager.properties +++ b/controlloop/common/controller-usecases/src/test/resources/config/event-manager.properties @@ -3,7 +3,7 @@ # ONAP # =============================================================================== # Copyright (C) 2020-2022 AT&T Intellectual Property. All rights reserved. -# Modifications Copyright (C) 2023 Nordix Foundation. +# Modifications Copyright (C) 2023-2024 Nordix Foundation. # =============================================================================== # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -29,7 +29,7 @@ operation.history.dbType=H2 # Actor parameters # # Note: every operation must have at least one entry, otherwise it will not be -# configured and started. Thus some of them have a "placeholder" property. +# configured and started. Thus, some of them have a "placeholder" property. # #actor.service.XACML.disabled=true @@ -45,16 +45,16 @@ actor.service.AAI.operations.CustomQuery.path=aai/v21/query actor.service.AAI.operations.Pnf.path=aai/v21/network/pnfs/pnf actor.service.AAI.operations.Tenant.path=aai/v21/search/nodes-query -actor.service.APPC.sinkTopic=APPC-LCM-READ -actor.service.APPC.sourceTopic=APPC-LCM-WRITE +actor.service.APPC.sinkTopic=appc-lcm-read +actor.service.APPC.sourceTopic=appc-lcm-write actor.service.APPC.operations.ConfigModify.placeholder= actor.service.APPC.operations.Migrate.placeholder= actor.service.APPC.operations.Restart.placeholder= actor.service.APPC.operations.Rebuild.placeholder= # legacy APPC - must specify sink and source for each operation -actor.service.APPC.operations.ModifyConfig.sinkTopic=APPC-CL -actor.service.APPC.operations.ModifyConfig.sourceTopic=APPC-CL +actor.service.APPC.operations.ModifyConfig.sinkTopic=appc-cl +actor.service.APPC.operations.ModifyConfig.sourceTopic=appc-cl actor.service.CDS.operations.any.host=localhost actor.service.CDS.operations.any.port=7878 @@ -68,12 +68,12 @@ actor.service.SDNC.operations.BandwidthOnDemand.path=\ actor.service.SDNC.operations.Reroute.path=\ GENERIC-RESOURCE-API:network-topology-operation -actor.service.SDNR.sinkTopic=SDNR-CL -actor.service.SDNR.sourceTopic=SDNR-CL-RSP +actor.service.SDNR.sinkTopic=sdnr-cl +actor.service.SDNR.sourceTopic=sdnr-cl-rsp actor.service.SDNR.operations.any.placeholder= -actor.service.A1P.sinkTopic=A1-P -actor.service.A1P.sourceTopic=A1-P-RSP +actor.service.A1P.sinkTopic=a1-p +actor.service.A1P.sourceTopic=a1-p-rsp actor.service.A1P.operations.any.placeholder= actor.service.SO.clientName=SO diff --git a/controlloop/common/controller-usecases/src/test/resources/config/usecases-controller.properties b/controlloop/common/controller-usecases/src/test/resources/config/usecases-controller.properties index dd1d35fca..67d0bc854 100644 --- a/controlloop/common/controller-usecases/src/test/resources/config/usecases-controller.properties +++ b/controlloop/common/controller-usecases/src/test/resources/config/usecases-controller.properties @@ -3,6 +3,7 @@ # ONAP # ================================================================================ # Copyright (C) 2020,2022 AT&T Intellectual Property. All rights reserved. +# Modifications Copyright (C) 2024 Nordix Foundation. # ================================================================================ # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -24,44 +25,44 @@ rules.groupId=org.onap.policy.controlloop rules.artifactId=usecases rules.version=1.1.0 -noop.source.topics=DCAE_TOPIC,APPC-CL,APPC-LCM-WRITE,SDNR-CL-RSP,POLICY-CL-MGT,APPC-LCM-READ,A1-P-RSP +noop.source.topics=dcae_topic,appc-cl,appc-lcm-write,sdnr-cl-rsp,policy-cl-mgt,appc-lcm-read,a1-p-rsp -noop.source.topics.DCAE_TOPIC.events=\ +noop.source.topics.dcae_topic.events=\ org.onap.policy.controlloop.CanonicalOnset,org.onap.policy.controlloop.CanonicalAbated -noop.source.topics.DCAE_TOPIC.events.org.onap.policy.controlloop.CanonicalOnset.\ +noop.source.topics.dcae_topic.events.org.onap.policy.controlloop.CanonicalOnset.\ filter=[?($.closedLoopEventStatus == 'ONSET')] -noop.source.topics.DCAE_TOPIC.events.org.onap.policy.controlloop.CanonicalAbated.\ +noop.source.topics.dcae_topic.events.org.onap.policy.controlloop.CanonicalAbated.\ filter=[?($.closedLoopEventStatus == 'ABATED')] -noop.source.topics.DCAE_TOPIC.events.custom.gson=org.onap.policy.controlloop.util.Serialization,gson +noop.source.topics.dcae_topic.events.custom.gson=org.onap.policy.controlloop.util.Serialization,gson -noop.source.topics.APPC-CL.events=org.onap.policy.appc.Response,org.onap.policy.appc.Request -noop.source.topics.APPC-CL.events.org.onap.policy.appc.Response.filter=[?($.CommonHeader && $.Status)] -noop.source.topics.APPC-CL.events.org.onap.policy.appc.Request.filter=[?($.CommonHeader && $.Action)] -noop.source.topics.APPC-CL.events.custom.gson=org.onap.policy.appc.util.Serialization,gsonPretty +noop.source.topics.appc-cl.events=org.onap.policy.appc.Response,org.onap.policy.appc.Request +noop.source.topics.appc-cl.events.org.onap.policy.appc.Response.filter=[?($.CommonHeader && $.Status)] +noop.source.topics.appc-cl.events.org.onap.policy.appc.Request.filter=[?($.CommonHeader && $.Action)] +noop.source.topics.appc-cl.events.custom.gson=org.onap.policy.appc.util.Serialization,gsonPretty -noop.source.topics.APPC-LCM-WRITE.events=org.onap.policy.appclcm.AppcLcmDmaapWrapper -noop.source.topics.APPC-LCM-WRITE.events.org.onap.policy.appclcm.AppcLcmDmaapWrapper.filter=[?($.type == 'response')] -noop.source.topics.APPC-LCM-WRITE.events.custom.gson=org.onap.policy.appclcm.util.Serialization,gson +noop.source.topics.appc-lcm-write.events=org.onap.policy.appclcm.AppcLcmDmaapWrapper +noop.source.topics.appc-lcm-write.events.org.onap.policy.appclcm.AppcLcmDmaapWrapper.filter=[?($.type == 'response')] +noop.source.topics.appc-lcm-write.events.custom.gson=org.onap.policy.appclcm.util.Serialization,gson -noop.source.topics.SDNR-CL-RSP.events=org.onap.policy.sdnr.PciResponseWrapper -noop.source.topics.SDNR-CL-RSP.events.org.onap.policy.sdnr.PciResponseWrapper.filter=[?($.type == 'response')] -noop.source.topics.SDNR-CL-RSP.events.custom.gson=org.onap.policy.sdnr.util.Serialization,gson +noop.source.topics.sdnr-cl-rsp.events=org.onap.policy.sdnr.PciResponseWrapper +noop.source.topics.sdnr-cl-rsp.events.org.onap.policy.sdnr.PciResponseWrapper.filter=[?($.type == 'response')] +noop.source.topics.sdnr-cl-rsp.events.custom.gson=org.onap.policy.sdnr.util.Serialization,gson -noop.source.topics.A1-P-RSP.events=org.onap.policy.sdnr.PciResponseWrapper -noop.source.topics.A1-P-RSP.events.org.onap.policy.sdnr.PciResponseWrapper.filter=[?($.type == 'response')] -noop.source.topics.A1-P-RSP.events.custom.gson=org.onap.policy.sdnr.util.Serialization,gson +noop.source.topics.a1-p-RSP.events=org.onap.policy.sdnr.PciResponseWrapper +noop.source.topics.a1-p-RSP.events.org.onap.policy.sdnr.PciResponseWrapper.filter=[?($.type == 'response')] +noop.source.topics.a1-p-RSP.events.custom.gson=org.onap.policy.sdnr.util.Serialization,gson -noop.source.topics.POLICY-CL-MGT.events=org.onap.policy.controlloop.VirtualControlLoopNotification -noop.source.topics.POLICY-CL-MGT.events.custom.gson=org.onap.policy.controlloop.util.Serialization,gsonPretty +noop.source.topics.policy-cl-mgt.events=org.onap.policy.controlloop.VirtualControlLoopNotification +noop.source.topics.policy-cl-mgt.events.custom.gson=org.onap.policy.controlloop.util.Serialization,gsonPretty -noop.source.topics.APPC-LCM-READ.events=org.onap.policy.appclcm.AppcLcmDmaapWrapper -noop.source.topics.APPC-LCM-READ.events.custom.gson=org.onap.policy.appclcm.util.Serialization,gson +noop.source.topics.appc-lcm-read.events=org.onap.policy.appclcm.AppcLcmDmaapWrapper +noop.source.topics.appc-lcm-read.events.custom.gson=org.onap.policy.appclcm.util.Serialization,gson -noop.sink.topics=APPC-CL,APPC-LCM-READ,POLICY-CL-MGT,SDNR-CL,DCAE_CL_RSP,A1-P +noop.sink.topics=appc-cl,appc-lcm-read,policy-cl-mgt,sdnr-cl,dcae_cl_rsp,a1-p -noop.sink.topics.POLICY-CL-MGT.events=org.onap.policy.controlloop.VirtualControlLoopNotification -noop.sink.topics.POLICY-CL-MGT.events.custom.gson=org.onap.policy.controlloop.util.Serialization,gsonPretty +noop.sink.topics.policy-cl-mgt.events=org.onap.policy.controlloop.VirtualControlLoopNotification +noop.sink.topics.policy-cl-mgt.events.custom.gson=org.onap.policy.controlloop.util.Serialization,gsonPretty -noop.sink.topics.DCAE_CL_RSP.events=org.onap.policy.controlloop.ControlLoopResponse -noop.sink.topics.DCAE_CL_RSP.events.custom.gson=org.onap.policy.controlloop.util.Serialization,gsonPretty +noop.sink.topics.dcae_cl_rsp.events=org.onap.policy.controlloop.ControlLoopResponse +noop.sink.topics.dcae_cl_rsp.events.custom.gson=org.onap.policy.controlloop.util.Serialization,gsonPretty diff --git a/controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/BaseTest.java b/controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/BaseTest.java index c2e10dff6..321938240 100644 --- a/controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/BaseTest.java +++ b/controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/BaseTest.java @@ -3,7 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2020-2022 AT&T Intellectual Property. All rights reserved. - * Modifications Copyright (C) 2023 Nordix Foundation. + * Modifications Copyright (C) 2023-2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,7 +29,6 @@ import java.util.Map; import java.util.UUID; import java.util.concurrent.TimeUnit; import java.util.function.Supplier; -import java.util.stream.Collectors; import java.util.stream.Stream; import lombok.AccessLevel; import lombok.Getter; @@ -66,15 +65,15 @@ public abstract class BaseTest { /* * Canonical Topic Names. */ - protected static final String DCAE_TOPIC = "DCAE_TOPIC"; - protected static final String APPC_LCM_WRITE_TOPIC = "APPC-LCM-WRITE"; - protected static final String POLICY_CL_MGT_TOPIC = "POLICY-CL-MGT"; - protected static final String APPC_LCM_READ_TOPIC = "APPC-LCM-READ"; - protected static final String APPC_CL_TOPIC = "APPC-CL"; - protected static final String SDNR_CL_TOPIC = "SDNR-CL"; - protected static final String SDNR_CL_RSP_TOPIC = "SDNR-CL-RSP"; - protected static final String A1P_CL_TOPIC = "A1-P"; - protected static final String A1P_CL_RSP_TOPIC = "A1-P-RSP"; + protected static final String DCAE_TOPIC = "dcae_topic"; + protected static final String APPC_LCM_WRITE_TOPIC = "appc-lcm-write"; + protected static final String POLICY_CL_MGT_TOPIC = "policy-cl-mgt"; + protected static final String APPC_LCM_READ_TOPIC = "appc-lcm-read"; + protected static final String APPC_CL_TOPIC = "appc-cl"; + protected static final String SDNR_CL_TOPIC = "sdnr-cl"; + protected static final String SDNR_CL_RSP_TOPIC = "sdnr-cl-rsp"; + protected static final String A1P_CL_TOPIC = "a1-p"; + protected static final String A1P_CL_RSP_TOPIC = "a1-p-rsp"; /* * Constants for each test case. @@ -289,7 +288,7 @@ public abstract class BaseTest { // get the list of target names, so we can ensure there's one of each List actual = Stream.of(notif1, notif2).map(notif -> notif.getAai().get("generic-vnf.vnf-id")) - .sorted().collect(Collectors.toList()); + .sorted().toList(); assertEquals(List.of("duplicate-VNF", "vCPE_Infrastructure_vGMUX_demo_app").toString(), actual.toString()); diff --git a/controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/Rules.java b/controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/Rules.java index 8272205d2..05d037e91 100644 --- a/controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/Rules.java +++ b/controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/Rules.java @@ -3,7 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2020-2022 AT&T Intellectual Property. All rights reserved. - * Modifications Copyright (C) 2023 Nordix Foundation. + * Modifications Copyright (C) 2023-2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -71,6 +71,7 @@ import org.slf4j.LoggerFactory; /** * Mechanism by which junit tests can manage the rule engine. */ +@Getter public class Rules { private static final Logger logger = LoggerFactory.getLogger(Rules.class); private static final StandardCoder coder = new StandardCoder(); @@ -79,20 +80,16 @@ public class Rules { /** * PDP-D Engine. */ - @Getter private final PolicyEngine pdpd = makeEngine(); /** * PDP-D Configuration Repository. */ - @Getter private final SystemPersistence pdpdRepo = makePdpdRepo(); - @Getter private final String controllerName; - @Getter private PolicyController controller; -- cgit 1.2.3-korg