0

我正在尝试将 Dynatrace App Mon 插件扩展为与 Jenkins 管道兼容。我从Github dynatrace-dashboard-2.0.5获取了源代码(来自这个存储库的主分支和dynatrace github 存储库的源代码有一些问题并且无法正常工作,所以我最终下载了 2.0.5 版本的源代码)

我写了一个类DynatraceAppMonBuildEnvStep来扩展AbstractStepImpl和模仿TABuildWrapperstep 的功能。Utils.updateBuildVariables(build, parameters);在类中调用方法 时遇到问题DynatraceAppMonBuildEnvStep,最终将设置环境变量。我没有收到任何错误/异常,但它没有设置我需要在mvn build命令中注入的环境变量。

当我bat 'set'在我的管道脚本中运行时,它不会显示在环境变量下方。如果我通过非管道调用插件,我可以看到这些环境变量。

dtMarker=testservice
dtPassword=password1
dtProfile=testprofile
dtServerUrl=https://<someurl>:8021
dtTestrunID=<test id>
dtUsername=<username>
dtVersionBuild=36
dtVersionMajor=testservice

代码流程如下:DynatraceAppMonBuildEnvStep -> Utils -> DynatraceVariablesAction -> DynatraceVariablesEnvironmentContributor -> buildEnvironmentFor(方法)。

DynatraceAppMonBuildEnvStep.java

    package com.dynatrace.jenkins.steps;

    import hudson.Extension;
    import hudson.model.ParameterValue;
    import hudson.model.PasswordParameterValue;
    import hudson.model.Run;
    import hudson.model.StringParameterValue;
    import hudson.model.TaskListener;
    import hudson.util.FormValidation;
    import jenkins.model.GlobalConfiguration;
    import org.apache.commons.lang.StringUtils;
    import org.jenkinsci.plugins.workflow.steps.AbstractStepDescriptorImpl;
    import org.jenkinsci.plugins.workflow.steps.AbstractStepImpl;
    import org.jenkinsci.plugins.workflow.steps.AbstractSynchronousNonBlockingStepExecution;
    import org.jenkinsci.plugins.workflow.steps.StepContextParameter;
    import org.kohsuke.stapler.DataBoundConstructor;
    import org.kohsuke.stapler.QueryParameter;
    import com.dynatrace.jenkins.dashboard.Messages;
    import com.dynatrace.jenkins.dashboard.TABuildSetupStatusAction;
    import com.dynatrace.jenkins.dashboard.TAGlobalConfiguration;
    import com.dynatrace.jenkins.dashboard.utils.BuildVarKeys;
    import com.dynatrace.jenkins.dashboard.utils.Utils;
    import com.dynatrace.sdk.server.exceptions.ServerResponseException;
    import com.dynatrace.sdk.server.sessions.Sessions;
    import com.dynatrace.sdk.server.sessions.models.StartRecordingRequest;
    import com.dynatrace.sdk.server.testautomation.TestAutomation;
    import com.dynatrace.sdk.server.testautomation.models.FetchTestRunsRequest;
    import com.sun.jersey.api.client.ClientHandlerException;
    import static java.net.HttpURLConnection.HTTP_FORBIDDEN;
    import static java.net.HttpURLConnection.HTTP_NOT_FOUND;
    import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED;
    import java.io.PrintStream;
    import java.net.URI;
    import java.util.ArrayList;
    import java.util.List;
    import javax.annotation.Nonnull;
    import javax.inject.Inject;
    import javax.net.ssl.SSLHandshakeException;

    public final class DynatraceAppMonBuildEnvStep extends AbstractStepImpl {

        /**
         * The 1st arg is system profile name, the 2nd is build number
         */
        private static final String RECORD_SESSION_NAME = "%s_Jenkins_build_%s";
        public final String systemProfile;
        // Test run attributes - no versionBuild attribute because it's taken from
        // the build object
        public final String versionMajor;
        public final String versionMinor;
        public final String versionRevision;
        public final String versionMilestone;
        public final String marker;
        public final Boolean recordSession;

        @DataBoundConstructor
        public DynatraceAppMonBuildEnvStep(final String systemProfile, final String versionMajor, final String versionMinor,
                final String versionRevision, final String versionMilestone, final String marker,
                final Boolean recordSession) {
            this.systemProfile = systemProfile;
            this.versionMajor = versionMajor;
            this.versionMinor = versionMinor;
            this.versionRevision = versionRevision;
            this.versionMilestone = versionMilestone;
            this.marker = marker;
            this.recordSession = recordSession;
        }

        private void setupBuildVariables(Run<?, ?> build, String serverUrl) {
            final TAGlobalConfiguration globalConfig = GlobalConfiguration.all().get(TAGlobalConfiguration.class);

            List<ParameterValue> parameters = new ArrayList<>(10);
            parameters.add(new StringParameterValue(BuildVarKeys.BUILD_VAR_KEY_SYSTEM_PROFILE, systemProfile));
            if (StringUtils.isNotEmpty(versionMajor)) {
                parameters.add(new StringParameterValue(BuildVarKeys.BUILD_VAR_KEY_VERSION_MAJOR, versionMajor));
            }
            if (StringUtils.isNotEmpty(versionMinor)) {
                parameters.add(new StringParameterValue(BuildVarKeys.BUILD_VAR_KEY_VERSION_MINOR, versionMinor));
            }
            if (StringUtils.isNotEmpty(versionRevision)) {
                parameters.add(new StringParameterValue(BuildVarKeys.BUILD_VAR_KEY_VERSION_REVISION, versionRevision));
            }
            parameters.add(new StringParameterValue(BuildVarKeys.BUILD_VAR_KEY_VERSION_BUILD,
                    Integer.toString(build.getNumber())));
            if (StringUtils.isNotEmpty(versionMilestone)) {
                parameters.add(new StringParameterValue(BuildVarKeys.BUILD_VAR_KEY_VERSION_MILESTONE, versionMilestone));
            }
            if (StringUtils.isNotEmpty(marker)) {
                parameters.add(new StringParameterValue(BuildVarKeys.BUILD_VAR_KEY_MARKER, marker));
            }
            if (StringUtils.isNotEmpty(serverUrl)) {
                parameters.add(new StringParameterValue(BuildVarKeys.BUILD_VAR_KEY_GLOBAL_SERVER_URL, serverUrl));
            }
            if (StringUtils.isNotEmpty(globalConfig.username)) {
                parameters.add(new StringParameterValue(BuildVarKeys.BUILD_VAR_KEY_GLOBAL_USERNAME, globalConfig.username));
            }
            if (StringUtils.isNotEmpty(globalConfig.password)) {
                parameters
                        .add(new PasswordParameterValue(BuildVarKeys.BUILD_VAR_KEY_GLOBAL_PASSWORD, globalConfig.password));
            }
            System.out.println("first call to utlis.updateBuildVariables from step 1::::");
            Utils.updateBuildVariables(build, parameters);
        }

        @Extension
        public static final class DescriptorImpl extends AbstractStepDescriptorImpl {

            public DescriptorImpl() {
                super(Execution.class);
            }

            @Override
            public String getFunctionName() {
                return "dynatraceAppMonBuildEnvStep";
            }

            private static final boolean DEFAULT_RECORD_SESSION = false;

            public static boolean getDefaultRecordSession() {
                return DEFAULT_RECORD_SESSION;
            }

            @Nonnull
            @Override
            public String getDisplayName() {
                return "Use Dynatrace AppMon to monitor tests";
            }

            public FormValidation doCheckSystemProfile(@QueryParameter final String systemProfile) {
                if (StringUtils.isNotBlank(systemProfile)) {
                    return FormValidation.ok();
                } else {
                    return FormValidation.error(Messages.RECORDER_VALIDATION_BLANK_SYSTEM_PROFILE());
                }
            }

            public FormValidation doTestDynatraceConnection(@QueryParameter final String systemProfile) {
                try {
                    final TestAutomation connection = new TestAutomation(Utils.createClient());
                    FetchTestRunsRequest request = new FetchTestRunsRequest(systemProfile);
                    // We set many constraints to ENSURE no or few testruns are
                    // returned as this is testing the connection only
                    request.setVersionBuildFilter("1024");
                    request.setVersionMajorFilter("1024");
                    request.setMaxBuilds(1);
                    try {
                        connection.fetchTestRuns(request);
                    } catch (ServerResponseException e) {
                        switch (e.getStatusCode()) {
                        case HTTP_UNAUTHORIZED:
                            return FormValidation.warning(Messages.RECORDER_VALIDATION_CONNECTION_UNAUTHORIZED());
                        case HTTP_FORBIDDEN:
                            return FormValidation.warning(Messages.RECORDER_VALIDATION_CONNECTION_FORBIDDEN());
                        case HTTP_NOT_FOUND:
                            return FormValidation.warning(Messages.RECORDER_VALIDATION_CONNECTION_NOT_FOUND());
                        default:
                            return FormValidation
                                    .warning(Messages.RECORDER_VALIDATION_CONNECTION_OTHER_CODE(e.getStatusCode()));
                        }
                    }
                    return FormValidation.ok(Messages.RECORDER_VALIDATION_CONNECTION_OK());
                } catch (Exception e) {
                    e.printStackTrace();
                    if (e.getCause() instanceof ClientHandlerException
                            && e.getCause().getCause() instanceof SSLHandshakeException) {
                        return FormValidation.warning(Messages.RECORDER_VALIDATION_CONNECTION_CERT_EXCEPTION(e.toString()));
                    }
                    return FormValidation.warning(Messages.RECORDER_VALIDATION_CONNECTION_UNKNOWN(e.toString()));
                }
            }
        }

        public static final class Execution extends AbstractSynchronousNonBlockingStepExecution<Boolean> {

            @Inject
            private transient DynatraceAppMonBuildEnvStep step;

            // public final Boolean recordSession = step.recordSession;
            // public final Boolean recordSession = false;

            @StepContextParameter
            private transient TaskListener listener;

            @StepContextParameter
            private transient Run<?, ?> build;

            @Override
            protected Boolean run() throws Exception {
                Boolean result = true;

                final TAGlobalConfiguration globalConfig = GlobalConfiguration.all().get(TAGlobalConfiguration.class);
                final Sessions sessions = new Sessions(Utils.createClient());
                final PrintStream logger = listener.getLogger();
                // logger.println("host is:"+globalConfig.host);
                try {
                    String serverUrl = new URI(globalConfig.protocol, null, globalConfig.host, globalConfig.port, null,
                            null, null).toString();

                    if (step.recordSession) {
                        logger.println("Starting session recording via Dynatrace Server REST interface...");

                        StartRecordingRequest request = new StartRecordingRequest(step.systemProfile);
                        request.setPresentableName(
                                String.format(RECORD_SESSION_NAME, step.systemProfile, build.getNumber()));

                        final String sessionNameOut = sessions.startRecording(request);
                        logger.println("Dynatrace session " + sessionNameOut + " has been started");
                    }

                    step.setupBuildVariables(build, serverUrl);
                } catch (Exception e) {
                    e.printStackTrace();
                    build.addAction(new TABuildSetupStatusAction(true));
                    logger.println(
                            "ERROR: Dynatrace AppMon Plugin - build set up failed (see the stacktrace to get more information):\n"
                                    + e.toString());
                }

                // final PrintStream logger = listener.getLogger();
                /*
                 * logger.println("Dynatrace AppMon Plugin - build tear down...");
                 * try { if (recordSession) { final String storedSessionName =
                 * storeSession(logger); Utils.updateBuildVariable(build,
                 * BuildVarKeys.BUILD_VAR_KEY_STORED_SESSION_NAME,
                 * storedSessionName); } } catch (Exception e) {
                 * e.printStackTrace(); logger.
                 * println("ERROR: Dynatrace AppMon Plugin - build tear down failed (see the stacktrace to get more information):\n"
                 * + e.toString()); }
                 */
                return result;
            }

            private static final long serialVersionUID = 1L;

            /**
             * @return stored session name
             */
            /*
             * private String storeSession(final PrintStream logger) throws
             * ServerResponseException, ServerConnectionException { logger.
             * println("Storing session via Dynatrace Server REST interface...");
             * String sessionName = sessions.stopRecording(step.systemProfile);
             * logger.println("Dynatrace session " + sessionName +
             * " has been stored"); return sessionName; }
             */
        }
    }


**Utils.java**


        package com.dynatrace.jenkins.dashboard.utils;

        import com.dynatrace.jenkins.dashboard.TABuildSetupStatusAction;
        import com.dynatrace.jenkins.dashboard.TAGlobalConfiguration;
        import com.dynatrace.jenkins.dashboard.model_2_0_0.*;
        import com.dynatrace.sdk.server.BasicServerConfiguration;
        import com.dynatrace.sdk.server.DynatraceClient;
        import com.dynatrace.sdk.server.testautomation.models.TestRuns;
        import hudson.model.AbstractBuild;
        import hudson.model.ParameterValue;
        import hudson.model.Result;
        import hudson.model.Run;
        import hudson.model.StringParameterValue;
        import jenkins.model.GlobalConfiguration;

        import java.io.PrintStream;
        import java.text.DecimalFormat;
        import java.util.*;

        /**
         * Created by krzysztof.necel on 2016-01-25.
         */
        public final class Utils {
            public static final String TEST_MEASURE_UNIT_DEFAULT = "num";
            public static final String DYNATRACE_ICON_24_X_24_FILEPATH = "/plugin/dynatrace-dashboard/images/dynatrace_icon_24x24.png";
            public static final String DYNATRACE_ICON_48_X_48_FILEPATH = "/plugin/dynatrace-dashboard/images/dynatrace_icon_48x48.png";

            private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("#.##");
            private static final String FORMAT_DOUBLE_NULL_VALUE = "N/A";

            private Utils() {
            }

            public static DynatraceClient createClient() {
                final TAGlobalConfiguration globalConfig = GlobalConfiguration.all().get(TAGlobalConfiguration.class);
                BasicServerConfiguration config = new BasicServerConfiguration(globalConfig.username,
                        globalConfig.password,
                        globalConfig.protocol.startsWith("https"),
                        globalConfig.host,
                        globalConfig.port,
                        globalConfig.validateCerts,
                        //connection timeout, 0 stands for infinite
                        0);
                return new DynatraceClient(config);
            }

            public static TAReportDetails convertTestRuns(TestRuns sdkTestRuns) {
                ArrayList<TestRun> testRuns = new ArrayList<>();
                if (sdkTestRuns != null) {
                    for (com.dynatrace.sdk.server.testautomation.models.TestRun tr : sdkTestRuns.getTestRuns()) {
                        testRuns.add(convertTestRun(tr));
                    }
                }
                return new TAReportDetails(testRuns);
            }

            public static TestRun convertTestRun(com.dynatrace.sdk.server.testautomation.models.TestRun sdkTestRun) {
                List<TestResult> testResults = new ArrayList<>();
                for (com.dynatrace.sdk.server.testautomation.models.TestResult sdkResult : sdkTestRun.getTestResults()) {
                    testResults.add(convertTestResult(sdkResult));
                }
                Map<TestStatus, Integer> testRunSummary = new EnumMap<>(TestStatus.class);
                testRunSummary.put(TestStatus.FAILED, sdkTestRun.getFailedCount());
                testRunSummary.put(TestStatus.DEGRADED, sdkTestRun.getDegradedCount());
                testRunSummary.put(TestStatus.VOLATILE, sdkTestRun.getVolatileCount());
                testRunSummary.put(TestStatus.IMPROVED, sdkTestRun.getImprovedCount());
                testRunSummary.put(TestStatus.PASSED, sdkTestRun.getPassedCount());
                return new TestRun(testResults, testRunSummary, sdkTestRun.getId(), convertTestCategory(sdkTestRun.getCategory()));
            }

            public static TestResult convertTestResult(com.dynatrace.sdk.server.testautomation.models.TestResult sdkTestResult) {
                Set<TestMeasure> measures = new HashSet<>();
                for (com.dynatrace.sdk.server.testautomation.models.TestMeasure sdkMeasure : sdkTestResult.getMeasures()) {
                    measures.add(convertTestMeasure(sdkMeasure));
                }
                return new TestResult(new Date(sdkTestResult.getExecutionTime()), sdkTestResult.getName(), sdkTestResult.getPackageName(), sdkTestResult.getPlatform(), convertTestStatus(sdkTestResult.getStatus()), measures);
            }

            public static TestMeasure convertTestMeasure(com.dynatrace.sdk.server.testautomation.models.TestMeasure sdkTestMeasure) {
                String unit = sdkTestMeasure.getUnit() != null ? sdkTestMeasure.getUnit() : TEST_MEASURE_UNIT_DEFAULT;
                return new TestMeasure(sdkTestMeasure.getName(),
                        sdkTestMeasure.getMetricGroup(),
                        sdkTestMeasure.getExpectedMin(),
                        sdkTestMeasure.getExpectedMax(),
                        sdkTestMeasure.getValue(),
                        unit,
                        sdkTestMeasure.getViolationPercentage());
            }

            public static TestCategory convertTestCategory(com.dynatrace.sdk.server.testautomation.models.TestCategory sdkTestCategory) {
                switch (sdkTestCategory) {
                    case UNIT:
                        return TestCategory.UNIT;
                    case UI_DRIVEN:
                        return TestCategory.UI_DRIVEN;
                    case WEB_API:
                        return TestCategory.WEB_API;
                    case PERFORMANCE:
                        return TestCategory.PERFORMANCE;
                }
                throw new IllegalArgumentException("Could not convert TestCategory");
            }

            public static TestStatus convertTestStatus(com.dynatrace.sdk.server.testautomation.models.TestStatus sdkTestStatus) {
                return TestStatus.valueOf(sdkTestStatus.name());
            }


            public static Map<TestStatus, Integer> createReportAggregatedSummary(TAReportDetails reportDetails) {
                // just sum all the reports for test runs
                final Map<TestStatus, Integer> summary = new EnumMap<>(TestStatus.class);
                for (TestRun testRun : reportDetails.getTestRuns()) {
                    Map<TestStatus, Integer> testRunSummary = testRun.getSummary();
                    for (Map.Entry<TestStatus, Integer> entry : testRunSummary.entrySet()) {
                        Integer value = summary.get(entry.getKey());
                        summary.put(entry.getKey(), value == null ? entry.getValue() : entry.getValue() + value);
                    }
                }
                return summary;
            }

            public static String formatDouble(Double d) {
                return d == null ? FORMAT_DOUBLE_NULL_VALUE : DECIMAL_FORMAT.format(d);
            }

            public static String formatDoublePercentage(Double d) {
                return d == null ? FORMAT_DOUBLE_NULL_VALUE : DECIMAL_FORMAT.format(d * 100);
            }

            public static boolean isValidBuild(AbstractBuild build, PrintStream logger, String message) {
                if (build.getResult() == Result.ABORTED) {
                    logger.println("Build has been aborted - " + message);
                    return false;
                }
                TABuildSetupStatusAction setupStatusAction = build.getAction(TABuildSetupStatusAction.class);
                if (setupStatusAction != null && setupStatusAction.isSetupFailed()) {
                    logger.println("Failed to set up environment for Dynatrace AppMon Plugin - " + message);
                    return false;
                }
                return true;
            }

            public static boolean isValidBuild(Run build, PrintStream logger, String message) {
                if (build.getResult() == Result.ABORTED) {
                    logger.println("Build has been aborted - " + message);
                    return false;
                }
                TABuildSetupStatusAction setupStatusAction = build.getAction(TABuildSetupStatusAction.class);
                if (setupStatusAction != null && setupStatusAction.isSetupFailed()) {
                    logger.println("Failed to set up environment for Dynatrace AppMon Plugin - " + message);
                    return false;
                }
                return true;
            }

            public static void updateBuildVariables(AbstractBuild<?, ?> build, List<ParameterValue> parameters) {
                DynatraceVariablesAction existingAction = build.getAction(DynatraceVariablesAction.class);
                if (existingAction == null) {
                    build.addAction(new DynatraceVariablesAction(parameters));
                } else {
                    build.replaceAction(existingAction.createUpdated(parameters));
                }
            }

            public static void updateBuildVariables(Run<?, ?> build, List<ParameterValue> parameters) {
                DynatraceVariablesAction existingAction = build.getAction(DynatraceVariablesAction.class);
                if (existingAction == null) {
                    build.addAction(new DynatraceVariablesAction(parameters)); 
                } else {
                    build.replaceAction(existingAction.createUpdated(parameters));
                }
            }

            public static void updateBuildVariable(AbstractBuild<?, ?> build, String key, String value) {
                updateBuildVariables(build, Collections.<ParameterValue>singletonList(new StringParameterValue(key, value)));
            }

            public static void updateBuildVariable(Run<?, ?> build, String key, String value) {
                updateBuildVariables(build, Collections.<ParameterValue>singletonList(new StringParameterValue(key, value)));
            }
        }

**DynatraceVariablesAction.java**

        package com.dynatrace.jenkins.dashboard.utils;
            import hudson.EnvVars;
            import hudson.Extension;
            import hudson.model.*;

            import javax.annotation.Nonnull;
            import java.util.*;

            public class DynatraceVariablesAction extends ParametersAction {

                private List<ParameterValue> parameters = new ArrayList<>();

                public DynatraceVariablesAction(Collection<? extends ParameterValue> parameters) {
                    this.parameters.addAll(parameters);
                }

                @Override
                public List<ParameterValue> getParameters() {
                    return Collections.unmodifiableList(parameters);
                }

                @Override
                public ParameterValue getParameter(String name) {
                    for (ParameterValue p : parameters) {
                        if (p == null) continue;
                        if (p.getName().equals(name))
                            return p;
                    }
                    return null;
                }

                @Nonnull
                @Override
                public DynatraceVariablesAction createUpdated(Collection<? extends ParameterValue> overrides) {
                    List<ParameterValue> newParams = new ArrayList<>(overrides);

                    outer:
                    for (ParameterValue value : this.parameters) {
                        for (ParameterValue newParam : newParams) {
                            if (newParam.getName().equals(value.getName())) {
                                continue outer;
                            }
                        }
                        newParams.add(value);
                    }

                    return new DynatraceVariablesAction(newParams);
                }

                @Extension
                public static final class DynatraceBuildVariablesContributor extends BuildVariableContributor {

                    @Override
                    public void buildVariablesFor(AbstractBuild r, Map<String, String> variables) {
                        DynatraceVariablesAction a = r.getAction(DynatraceVariablesAction.class);
                        if (a == null) {
                            return;
                        }
                        for (ParameterValue spv : a.getParameters()) {
                            variables.put(spv.getName(), String.valueOf(spv.getValue()));
                        }
                    }
                }

                @Extension
                public static final class DynatraceVariablesEnvironmentContributor extends EnvironmentContributor {
                    @Override
                    public void buildEnvironmentFor(Run r, EnvVars vars, TaskListener listener) {
                        DynatraceVariablesAction a = r.getAction(DynatraceVariablesAction.class);
                        if (a == null) {
                            return;
                        }
                        for (ParameterValue spv : a.getParameters()) {
                            vars.put(spv.getName(), String.valueOf(spv.getValue()));
                        }
                    }
                }
    }


I also tried to set the environment variables by extending InvisibleAction class instead of ParametersAction, as performance-signature-dynatrace-plugin is doing but that didn't seem to work as well. Dynatrace performance signature plugin is setting the environment variables in a bit different way. See these two links: 
[https://github.com/jenkinsci/performance-signature-dynatrace-plugin/blob/master/dynatrace/src/main/java/de/tsystems/mms/apm/performancesignature/dynatrace/PerfSigEnvInvisAction.java][1] 

[https://github.com/jenkinsci/performance-signature-dynatrace-plugin/blob/master/dynatrace/src/main/java/de/tsystems/mms/apm/performancesignature/dynatrace/PerfSigEnvContributor.java][2]


  [1]: https://github.com/jenkinsci/performance-signature-dynatrace-plugin/blob/master/dynatrace/src/main/java/de/tsystems/mms/apm/performancesignature/dynatrace/PerfSigEnvInvisAction.java
  [2]: https://github.com/jenkinsci/performance-signature-dynatrace-plugin/blob/master/dynatrace/src/main/java/de/tsystems/mms/apm/performancesignature/dynatrace/PerfSigEnvContributor.java


Any help would be highly appreciated. I hope I was able to describe the problem. Please feel free to comment if my issue/question is not clear.

Thanks.
4

0 回答 0