• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

HicServices / RDMP / 6237307473

19 Sep 2023 04:02PM UTC coverage: 57.015% (-0.4%) from 57.44%
6237307473

push

github

web-flow
Feature/rc4 (#1570)

* Syntax tidying
* Dependency updates
* Event handling singletons (ThrowImmediately and co)

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: James A Sutherland <>
Co-authored-by: James Friel <jfriel001@dundee.ac.uk>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

10734 of 20259 branches covered (0.0%)

Branch coverage included in aggregate %.

5922 of 5922 new or added lines in 565 files covered. (100.0%)

30687 of 52390 relevant lines covered (58.57%)

7361.8 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/Rdmp.Core/CommandLine/RdmpCommandLineBootStrapper.cs
1
// Copyright (c) The University of Dundee 2018-2019
2
// This file is part of the Research Data Management Platform (RDMP).
3
// RDMP is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
4
// RDMP is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
5
// You should have received a copy of the GNU General Public License along with RDMP. If not, see <https://www.gnu.org/licenses/>.
6

7
using System;
8
using System.IO;
9
using CommandLine;
10
using NLog;
11
using Rdmp.Core.CommandExecution;
12
using Rdmp.Core.CommandLine.Options;
13
using Rdmp.Core.CommandLine.Runners;
14
using Rdmp.Core.DataFlowPipeline;
15
using Rdmp.Core.Logging.Listeners.NLogListeners;
16
using Rdmp.Core.MapsDirectlyToDatabaseTable;
17
using Rdmp.Core.Repositories;
18
using Rdmp.Core.ReusableLibraryCode;
19
using Rdmp.Core.ReusableLibraryCode.Checks;
20
using Rdmp.Core.ReusableLibraryCode.Progress;
21
using Rdmp.Core.Startup;
22
using YamlDotNet.Serialization;
23

24
namespace Rdmp.Core.CommandLine;
25

26
/// <summary>
27
/// Parses strings into relevant <see cref="RDMPCommandLineOptions"/> subclasses
28
/// and runs appropriate <see cref="Runners.Runner"/>
29
/// </summary>
30
public class RdmpCommandLineBootStrapper
31
{
32
    public static int HandleArgumentsWithStandardRunner(string[] args, Logger logger,
33
        IRDMPPlatformRepositoryServiceLocator existingLocator = null)
34
    {
35
        try
36
        {
37
            var returnCode = UsefulStuff.GetParser()
×
38
                .ParseArguments<
×
39
                    DleOptions,
×
40
                    DqeOptions,
×
41
                    CacheOptions,
×
42
                    ExtractionOptions,
×
43
                    ReleaseOptions,
×
44
                    CohortCreationOptions,
×
45
                    ExecuteCommandOptions>(args)
×
46
                .MapResult(
×
47
                    //Add new verbs as options here and invoke relevant runner
×
48
                    (DleOptions opts) => Run(opts, null, existingLocator),
×
49
                    (DqeOptions opts) => Run(opts, null, existingLocator),
×
50
                    (CacheOptions opts) => Run(opts, null, existingLocator),
×
51
                    (ExtractionOptions opts) => Run(opts, null, existingLocator),
×
52
                    (ReleaseOptions opts) => Run(opts, null, existingLocator),
×
53
                    (CohortCreationOptions opts) => Run(opts, null, existingLocator),
×
54
                    (ExecuteCommandOptions opts) => RunCmd(opts, existingLocator),
×
55
                    errs => 1);
×
56

57
            logger.Info($"Exiting with code {returnCode}");
×
58
            return returnCode;
×
59
        }
60
        catch (Exception e)
×
61
        {
62
            logger.Error(e.Message);
×
63
            logger.Info(e, "Fatal error occurred so returning -1");
×
64
            return -1;
×
65
        }
66
    }
×
67

68
    public static int RunCmd(ExecuteCommandOptions opts, IRDMPPlatformRepositoryServiceLocator existingLocator = null)
69
    {
70
        if (!string.IsNullOrWhiteSpace(opts.File))
×
71
        {
72
            if (!File.Exists(opts.File))
×
73
            {
74
                Console.WriteLine($"Could not find file '{opts.File}'");
×
75
                return -55;
×
76
            }
77

78
            var content = File.ReadAllText(opts.File);
×
79

80
            if (string.IsNullOrWhiteSpace(content))
×
81
            {
82
                Console.WriteLine($"File is empty ('{opts.File}')");
×
83
                return -56;
×
84
            }
85

86
            try
87
            {
88
                var d = new Deserializer();
×
89
                opts.Script = d.Deserialize<RdmpScript>(content);
×
90
            }
×
91
            catch (Exception ex)
×
92
            {
93
                Console.WriteLine($"Error deserializing '{opts.File}': {ex.Message}");
×
94
                return -57;
×
95
            }
96
        }
97

98
        return Run((RDMPCommandLineOptions)opts, null, existingLocator);
×
99
    }
×
100

101
    public static int Run(RDMPCommandLineOptions opts, IRunner explicitRunner = null,
102
        IRDMPPlatformRepositoryServiceLocator existingLocator = null)
103
    {
104
        // if we have already done startup great!
105
        var repositoryLocator = existingLocator;
×
106

107
        var listener = new NLogIDataLoadEventListener(false);
×
108
        var checker = new NLogICheckNotifier(true, false);
×
109

110
        // not done startup so check that we can reach stuff
111
        if (repositoryLocator == null)
×
112
        {
113
            opts.PopulateConnectionStringsFromYamlIfMissing(ThrowImmediatelyCheckNotifier.Quiet);
×
114

115
            // where RDMP objects are stored
116
            repositoryLocator = opts.GetRepositoryLocator();
×
117

118
            if (repositoryLocator?.CatalogueRepository == null)
×
119
            {
120
                listener.OnNotify(typeof(RdmpCommandLineBootStrapper),
×
121
                    new NotifyEventArgs(ProgressEventType.Error,
×
122
                        "No repository has been specified.  Either create a Databases.yaml file or provide repository connection strings/paths as command line arguments"));
×
123
                return REPO_ERROR;
×
124
            }
125

126

127
            if (!CheckRepo(repositoryLocator)) return REPO_ERROR;
×
128

129
            CatalogueRepository.SuppressHelpLoading = false;
×
130
            opts.DoStartup(opts.LogStartup ? checker : IgnoreAllErrorsCheckNotifier.Instance);
×
131
        }
132

133
        //if user wants to run checking chances are they don't want checks to fail because of errors logged during startup (MEF shows lots of errors!)
134
        if (opts.LogStartup && opts.Command == CommandLineActivity.check)
×
135
            checker.Worst = LogLevel.Info;
×
136

137
        var runner = explicitRunner ??
×
138
                     RunnerFactory.CreateRunner(new ThrowImmediatelyActivator(repositoryLocator, checker), opts);
×
139

140
        // Let's not worry about global errors during the CreateRunner process
141
        // These are mainly UI/GUI and unrelated to the actual process to run
142
        if (checker.Worst > LogLevel.Warn)
×
143
            checker.Worst = LogLevel.Warn;
×
144

145
        var runExitCode = runner.Run(repositoryLocator, listener, checker, new GracefulCancellationToken());
×
146

147
        if (opts.Command == CommandLineActivity.check)
×
148
            checker.OnCheckPerformed(checker.Worst <= LogLevel.Warn
×
149
                ? new CheckEventArgs("Checks Passed", CheckResult.Success)
×
150
                : new CheckEventArgs("Checks Failed", CheckResult.Fail));
×
151

152
        if (runExitCode != 0)
×
153
            return runExitCode;
×
154

155
        //or if either listener reports error
156
        if (listener.Worst >= LogLevel.Error || checker.Worst >= LogLevel.Error)
×
157
            return -1;
×
158

159
        return opts.FailOnWarnings && (listener.Worst >= LogLevel.Warn || checker.Worst >= LogLevel.Warn) ? 1 : 0;
×
160
    }
161

162
    /// <summary>
163
    /// The error to return when there is a problem contacting the repository databases
164
    /// </summary>
165
    public const int REPO_ERROR = 7;
166

167
    public static bool CheckRepo(IRDMPPlatformRepositoryServiceLocator repo)
168
    {
169
        var logger = LogManager.GetCurrentClassLogger();
×
170
        if (repo is not LinkedRepositoryProvider l) return true;
×
171
        if (l.CatalogueRepository is TableRepository c)
×
172
            try
173
            {
174
                c.DiscoveredServer.TestConnection(15_000);
×
175
            }
×
176
            catch (Exception ex)
×
177
            {
178
                logger.Error(ex,
×
179
                    $"Could not reach {c.DiscoveredServer} (Database:{c.DiscoveredServer.GetCurrentDatabase()}).  Ensure that you have configured RDMP database connections in Databases.yaml correctly and/or that you have run install to setup platform databases");
×
180
                return false;
×
181
            }
182

183
        if (l.DataExportRepository is TableRepository d)
×
184
            try
185
            {
186
                d.DiscoveredServer.TestConnection();
×
187
            }
×
188
            catch (Exception ex)
×
189
            {
190
                logger.Error(ex,
×
191
                    $"Could not reach {d.DiscoveredServer} (Database:{d.DiscoveredServer.GetCurrentDatabase()}).  Ensure that you have configured RDMP database connections in Databases.yaml correctly and/or that you have run install to setup platform databases");
×
192
                return false;
×
193
            }
194

195
        return true;
×
196
    }
×
197
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc