diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000000000000000000000000000000000..1ff0c423042b46cb1d617b81efb715defbe8054d --- /dev/null +++ b/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..8d72a0b63cf3c83397169fc7d3561717c916b488 --- /dev/null +++ b/.gitignore @@ -0,0 +1,273 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Database connection for t4 class generation from database +**/*.generated.cs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +project.fragment.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user +Resharper + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +#*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignoreable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +node_modules/ +orleans.codegen.cs + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +#cake +tools/* +!tools/packages.config +dist/ + +#linq2db +src/.tools/ \ No newline at end of file diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000000000000000000000000000000000000..b339a45c43a1dcb4b80ab99e6224bc7232abd723 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,55 @@ +stages: + - test + - release + - releasetrigger + +cake:Test: + stage: test + script: + - PowerShell .\build.ps1 -Target Test -Configuration Debug + variables: + GIT_STRATEGY: clone + artifacts: + reports: + junit: "./Artifacts/TestResults.xml" + paths: + - "./Artifacts/*" + except: + - master + - tags + +cake:Release: + stage: release + script: + - PowerShell .\build.ps1 -Target Release -Configuration Release --nugetApiKey="${NUGET_API_KEY}" + variables: + GIT_STRATEGY: clone + dependencies: + - cake:Test + artifacts: + paths: + - "./Artifacts/*" + only: + - tags + +cake:Prerelease: + stage: release + script: + - PowerShell .\build.ps1 -Target Prerelease -Configuration Release + variables: + GIT_STRATEGY: clone + dependencies: + - cake:Test + artifacts: + paths: + - "./Artifacts/*" + except: + - tags + - master + +cake:GitlabRelease: + stage: releasetrigger + script: + - PowerShell .\build.ps1 -Target GitlabRelease --GitlabProjectPath="${CI_PROJECT_PATH}" --gitlabProjectId="${CI_PROJECT_ID}" --gitlabToken="${GITLAB_TOKEN}" + only: + - master \ No newline at end of file diff --git a/GitVersion.yml b/GitVersion.yml new file mode 100644 index 0000000000000000000000000000000000000000..1bdc0fe219f5f35d8a024a66d9fd715f44539640 --- /dev/null +++ b/GitVersion.yml @@ -0,0 +1,7 @@ +mode: ContinuousDeployment +next-version: 1.0.0 +major-version-bump-message: 'Breaking:' +minor-version-bump-message: '(Update|New):' +patch-version-bump-message: 'Fix:' +no-bump-message: '.*' +commit-message-incrementing: Enabled \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..1cacbda86167c5f5629e9d3f8605295ad009460f --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 RWTH Aachen University + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md index 06db01c5482fc6c2f4372a99f6dca0fd72a4a610..36ca3bfcbff4045a7130eac8c8d49aa561d9d377 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,28 @@ -# Kpi Generator +## ProxyApi -Generator gathering data for the KPIs for sending them to the web hamster. \ No newline at end of file +This Api can access the RWTHAppProxy and OAuth2 of the RWTH Aachen University. + +Furthermore some helper classes exists which can verify tokens for accessing certain Api methods. + +The following configuration keys are currently settable: + +* "coscine/global/context/metadata/scope" +* "coscine/global/context/metadata/serviceid" +* "coscine/global/context/coscine/scope" +* "coscine/global/context/coscine/serviceid" +* "coscine/local/proxytest/refreshtoken" <= A valid refresh token for testing +* "coscine/global/epic/prefix" +* "coscine/global/epic/url" +* "coscine/global/epic/user" +* "coscine/global/epic/password" + +## Building + +Build this project by running either the build.ps1 or the build<span></span>.sh script. +The project will be build and tested. + +### Links + +* [Commit convention](docs/ESLintConvention.md) +* [Everything possible with markup](docs/testdoc.md) +* [Adding NUnit tests](docs/nunit.md) \ No newline at end of file diff --git a/build.cake b/build.cake new file mode 100644 index 0000000000000000000000000000000000000000..81648ff61bbee492e1bc7b4390eb8e0cc33d3056 --- /dev/null +++ b/build.cake @@ -0,0 +1,351 @@ +#tool nuget:?package=NUnit.ConsoleRunner&version=3.10.0 +#tool nuget:?package=vswhere&version=2.8.4 +#tool nuget:?package=GitVersion.CommandLine&version=5.1.3 + +#addin nuget:https://api.nuget.org/v3/index.json?package=Cake.Json&version=4.0.0 +#addin nuget:https://api.nuget.org/v3/index.json?package=Newtonsoft.Json&version=11.0.2 +#addin nuget:https://api.nuget.org/v3/index.json?package=Cake.FileHelpers&version=3.2.1 + +using System.Net; +using System.Net.Http; + +// Commandline arguments +var target = Argument("target", "Default"); +var configuration = Argument("configuration", "Release"); +var nugetApiKey = Argument<string>("nugetApiKey", null); +var version = Argument("nugetVersion", ""); +var gitlabProjectPath = Argument("gitlabProjectPath", ""); +var gitlabProjectId = Argument("gitlabProjectId", ""); +var gitlabToken = Argument("gitlabToken", ""); + +// Define directories +var projects = GetFiles("./**/*.csproj"); +var artifactsDir = Directory("./Artifacts"); +string nupkgDir; +var solutionFile = GetFiles("./**/*.sln").First(); +var projectName = solutionFile.GetFilenameWithoutExtension().ToString(); +var nugetSource = "https://api.nuget.org/v3/index.json"; +var assemblyInfoSubPath = "Properties/AssemblyInfo.cs"; +var semanticVersion = ""; +string localNugetFeed; + +// get latest MSBuild version +var vsLatest = VSWhereLatest(); +var msBuildPathX64 = (vsLatest == null) ? null : vsLatest.CombineWithFilePath("./MSBuild/Current/Bin/MSBuild.exe"); + +Setup(context =>{ + nupkgDir = $"{artifactsDir.ToString()}/nupkg"; + var branch = GitVersion(new GitVersionSettings { + UpdateAssemblyInfo = false + }).BranchName.Replace("/", "-"); + + localNugetFeed = $"C:\\coscine\\LocalNugetFeeds\\{branch}"; + Information("{0}", branch); + Information("Started at {0}", DateTime.Now); +}); + +Teardown(context =>{ + Information("Finished at {0}", DateTime.Now); +}); + +Task("Clean") +.Description("Cleans all build and artifacts directories") +.Does(() =>{ + var settings = new DeleteDirectorySettings { + Recursive = true, + Force = true + }; + + var directoriesToClean = new List<DirectoryPath>(); + + foreach(var project in projects) { + directoriesToClean.Add(Directory($"{project.GetDirectory()}/obj")); + directoriesToClean.Add(Directory($"{project.GetDirectory()}/bin")); + } + + directoriesToClean.Add(artifactsDir); + + foreach(var dir in directoriesToClean) { + Information("Cleaning {0}", dir.ToString()); + if (DirectoryExists(dir)) { + DeleteDirectory(dir, settings); + CreateDirectory(dir); + } else { + CreateDirectory(dir); + } + } +}); + +Task("Restore") +.Does(() =>{ + NuGetRestore(solutionFile, new NuGetRestoreSettings { + NoCache = true, + FallbackSource = new List<string>{ localNugetFeed }, + }); +}); + +Task("Test") +.IsDependentOn("Build") +.Does(() =>{ + NUnit3($"./src/**/bin/{configuration}/*.Tests.dll", new NUnit3Settings { + // generate the xml file + NoResults = false, + Results = new NUnit3Result[] { + new NUnit3Result() { + FileName = $"{artifactsDir}/TestResults.xml", + Transform = $"{Context.Environment.WorkingDirectory}/nunit3-junit.xslt" + } + } + }); +}); + +Task("GitVersion") +.Does(() => { + if(string.IsNullOrWhiteSpace(version)) { + version = GitVersion(new GitVersionSettings { + UpdateAssemblyInfo = false + }).NuGetVersionV2; + } + var index = version.IndexOf("-"); + semanticVersion = index > 0 ? version.Substring(0, index) : version; + Information("Version: {0}, SemanticVersion: {1}", version, semanticVersion); +}); + +Task("UpdateAssemblyInfo") +.Does(() =>{ + var index = version.IndexOf("-"); + var semanticVersion = index > 0 ? version.Substring(0, index) : version; + + foreach(var project in projects) { + CreateAssemblyInfo($"{project.GetDirectory()}/{assemblyInfoSubPath}", new AssemblyInfoSettings { + Product = project.GetFilenameWithoutExtension().ToString(), + Title = project.GetFilenameWithoutExtension().ToString(), + Company = "IT Center, RWTH Aachen University", + Version = semanticVersion, + FileVersion = semanticVersion, + InformationalVersion = version, + Copyright = $"{DateTime.Now.Year} IT Center, RWTH Aachen University", + Description = $"{project.GetFilenameWithoutExtension().ToString()} is a part of the CoScInE group." + }); + } +}); + +Task("GitlabRelease") +.IsDependentOn("GitVersion") +.Does(() => { + var client = new HttpClient(); + client.DefaultRequestHeaders.Add("PRIVATE-TOKEN", gitlabToken); + + // get the latest tag + var result = client.GetAsync($"https://git.rwth-aachen.de/api/v4/projects/{gitlabProjectId}/repository/tags").Result; + if(!result.IsSuccessStatusCode) { + throw new Exception("Tag query failed."); + } + + var tagList = result.Content.ReadAsStringAsync().Result; + var jArray = JArray.Parse(tagList); + // null if not tags exists yet + var lastTag = jArray.Select(x => x["name"]).FirstOrDefault(); + + var url = $"https://git.rwth-aachen.de/{gitlabProjectPath}"; + + if(url.EndsWith(".git")) { + url = url.Substring(0, url.Length - ".git".Length); + } + + if(url.EndsWith("/")) { + url = url.Substring(0, url.Length - 1); + } + + var description = ""; + // First line of description + // Gitlab compare url, if something can be compared + if(lastTag == null) { + description = $"# {semanticVersion} ({DateTime.Now.Year}-{DateTime.Now.Month}-{DateTime.Now.Day})\n\n\n"; + } else { + description = $"# [{semanticVersion}]({url}/compare/{lastTag}...v{semanticVersion}) ({DateTime.Now.Year}-{DateTime.Now.Month}-{DateTime.Now.Day})\n\n\n"; + } + + // From when will messages be parsed, null results in all messages + var logParam = ""; + if(lastTag != null) { + logParam = $"{lastTag}..Head"; + } + + Information(lastTag); + + IEnumerable<string> redirectedStandardOutput; + var exitCodeWithArgument = + StartProcess( + "git", + new ProcessSettings { + Arguments = $"log {logParam} --pretty=format:HASH%h:%B", + RedirectStandardOutput = true + }, + out redirectedStandardOutput + ); + + var prefixList = new Dictionary<string, List<string>>{ + {"Fix", new List<string>()}, + {"Update", new List<string>()}, + {"New", new List<string>()}, + {"Breaking", new List<string>()}, + {"Docs", new List<string>()}, + {"Build", new List<string>()}, + {"Upgrade", new List<string>()}, + {"Chore", new List<string>()}, + }; + + var currentHash = ""; + // Output last line of process output. + foreach(var line in redirectedStandardOutput) { + var commitMessage = ""; + if(line.StartsWith("HASH")) { + currentHash = line.Substring("HASH".Length); + currentHash = currentHash.Substring(0, currentHash.IndexOf(":")); + commitMessage = line.Substring(currentHash.Length + line.IndexOf(currentHash) + 1); + } else { + commitMessage = line; + } + + foreach(var kv in prefixList) { + if(commitMessage.StartsWith($"{kv.Key}:")) { + kv.Value.Add($"* {commitMessage.Substring(kv.Key.Length + 1).Trim()} {currentHash}"); + break; + } + }; + } + + foreach(var kv in prefixList) { + if(kv.Value.Any()) { + description += $" ### {kv.Key}\n\n"; + foreach(var line in kv.Value) { + description += $"{line}\n"; + } + description += "\n"; + } + } + // correctly escape the json newlines + description = description.Replace("\n", "\\n"); + Information("Description: {0}", description); + + // create tag + result = client.PostAsync($"https://git.rwth-aachen.de/api/v4/projects/{gitlabProjectId}/repository/tags?tag_name=v{semanticVersion}&ref=master", null).Result; + Information("Create tag: {0}", result.Content.ReadAsStringAsync().Result); + if(!result.IsSuccessStatusCode) { + throw new Exception("Tag creation failed."); + } + + // create release + var json = $"{{\"name\": \"v{semanticVersion}\", \"tag_name\": \"v{semanticVersion}\", \"description\": \"{description}\"}}"; + var content = new StringContent(json, Encoding.UTF8, "application/json"); + result = client.PostAsync($"https://git.rwth-aachen.de/api/v4/projects/{gitlabProjectId}/releases", content).Result; + Information("Create release: {0}", result.Content.ReadAsStringAsync().Result); + if(!result.IsSuccessStatusCode) { + throw new Exception("Release creation failed."); + } +}); + +Task("Build") +.IsDependentOn("Clean") +.IsDependentOn("GitVersion") +.IsDependentOn("UpdateAssemblyInfo") +.IsDependentOn("Restore") +.Does(() =>{ + var frameworkSettingsWindows = new MSBuildSettings { + Configuration = configuration + }; + + frameworkSettingsWindows.ToolPath = msBuildPathX64; + frameworkSettingsWindows.WorkingDirectory = Context.Environment.WorkingDirectory; + + if (configuration.Equals("Release")) { + frameworkSettingsWindows.WithProperty("DebugSymbols", "false"); + frameworkSettingsWindows.WithProperty("DebugType", "None"); + } + + // Use MSBuild + Information("Building {0}", solutionFile); + MSBuild(solutionFile, frameworkSettingsWindows); +}); + +Task("NugetPack") +.IsDependentOn("Build") +.Does(() =>{ + foreach(var project in projects) { + var nuspec = $"{project.GetDirectory()}/{project.GetFilenameWithoutExtension()}.nuspec"; + if(!project.ToString().EndsWith(".Tests") && FileExists(nuspec)) + { + var settings = new NuGetPackSettings + { + OutputDirectory = nupkgDir, + Version = version, + Properties = new Dictionary<string, string> + { + { "Configuration", configuration} + } + }; + NuGetPack(project.ToString(), settings); + } + } +}); + +Task("NugetPush") +.IsDependentOn("NugetPack") +.Does(() =>{ + var nupkgs = GetFiles($"{nupkgDir}/*.nupkg"); + Information("Need to push {0} packages", nupkgs.Count); + if(!String.IsNullOrWhiteSpace(nugetApiKey)) { + foreach(var nupkg in nupkgs) { + Information("Pushing {0}", nupkg); + NuGetPush(nupkg, new NuGetPushSettings { + Source = nugetSource, + ApiKey = nugetApiKey + }); + } + } else { + Information("NugetApiKey is not set. Can't push."); + throw new Exception("NugetApiKey is not set. Can't push."); + } +}); + +Task("CopyToArtifacts") +.Does(() =>{ + foreach(var project in projects) { + if(!project.GetDirectory().ToString().EndsWith(".Tests") + && !FileExists($"{project.GetDirectory()}/{project.GetFilenameWithoutExtension()}.nuspec") + && DirectoryExists(project.GetDirectory())) + { + Information("Copying {0}/* to {1}", $"{project.GetDirectory()}/bin/{configuration}", artifactsDir); + CopyDirectory($"{project.GetDirectory()}/bin/{configuration}/", artifactsDir); + } + } +}); + +Task("NugetPushLocal") +.IsDependentOn("NugetPack") +.Does(() =>{ + var nupkgs = GetFiles($"{nupkgDir}/*.nupkg"); + foreach(var nupkg in nupkgs) { + if(!DirectoryExists(localNugetFeed)) { + CreateDirectory(localNugetFeed); + } + CopyFile(nupkg.ToString(), $"{localNugetFeed}\\{nupkg.GetFilename()}"); + } +}); + +Task("Prerelease") +.IsDependentOn("Build") +.IsDependentOn("CopyToArtifacts") +.IsDependentOn("NugetPushLocal"); + +Task("Release") +.IsDependentOn("NugetPack") +.IsDependentOn("CopyToArtifacts") +.IsDependentOn("NugetPushLocal") +.IsDependentOn("NugetPush"); + +Task("Default") +.IsDependentOn("Test"); + +RunTarget(target); diff --git a/build.ps1 b/build.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..f83382e8e4092ba6cf32a47f9dfa4e211c878430 --- /dev/null +++ b/build.ps1 @@ -0,0 +1,255 @@ +#The MIT License (MIT) +# +#Copyright (c) 2014 - 2016 Patrik Svensson, Mattias Karlsson, Gary Ewan Park and contributors +# +#Permission is hereby granted, free of charge, to any person obtaining a copy of +#this software and associated documentation files (the "Software"), to deal in +#the Software without restriction, including without limitation the rights to +#use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +#the Software, and to permit persons to whom the Software is furnished to do so, +#subject to the following conditions: +# +#The above copyright notice and this permission notice shall be included in all +#copies or substantial portions of the Software. +# +#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +#FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +#COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +#IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +#CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +########################################################################## +# This is the Cake bootstrapper script for PowerShell. +# This file was downloaded from https://github.com/cake-build/resources +# Feel free to change this file to fit your needs. +########################################################################## + +<# + +.SYNOPSIS +This is a Powershell script to bootstrap a Cake build. + +.DESCRIPTION +This Powershell script will download NuGet if missing, restore NuGet tools (including Cake) +and execute your Cake build script with the parameters you provide. + +.PARAMETER Script +The build script to execute. +.PARAMETER Target +The build script target to run. +.PARAMETER Configuration +The build configuration to use. +.PARAMETER Verbosity +Specifies the amount of information to be displayed. +.PARAMETER ShowDescription +Shows description about tasks. +.PARAMETER DryRun +Performs a dry run. +.PARAMETER Experimental +Uses the nightly builds of the Roslyn script engine. +.PARAMETER Mono +Uses the Mono Compiler rather than the Roslyn script engine. +.PARAMETER SkipToolPackageRestore +Skips restoring of packages. +.PARAMETER ScriptArgs +Remaining arguments are added here. + +.LINK +https://cakebuild.net + +#> + +[CmdletBinding()] +Param( + [string]$Script = "build.cake", + [string]$Target, + [string]$Configuration, + [ValidateSet("Quiet", "Minimal", "Normal", "Verbose", "Diagnostic")] + [string]$Verbosity, + [switch]$ShowDescription, + [Alias("WhatIf", "Noop")] + [switch]$DryRun, + [switch]$Experimental, + [switch]$Mono, + [switch]$SkipToolPackageRestore, + [Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)] + [string[]]$ScriptArgs +) + +[Reflection.Assembly]::LoadWithPartialName("System.Security") | Out-Null +function MD5HashFile([string] $filePath) +{ + if ([string]::IsNullOrEmpty($filePath) -or !(Test-Path $filePath -PathType Leaf)) + { + return $null + } + + [System.IO.Stream] $file = $null; + [System.Security.Cryptography.MD5] $md5 = $null; + try + { + $md5 = [System.Security.Cryptography.MD5]::Create() + $file = [System.IO.File]::OpenRead($filePath) + return [System.BitConverter]::ToString($md5.ComputeHash($file)) + } + finally + { + if ($file -ne $null) + { + $file.Dispose() + } + } +} + +function GetProxyEnabledWebClient +{ + $wc = New-Object System.Net.WebClient + $proxy = [System.Net.WebRequest]::GetSystemWebProxy() + $proxy.Credentials = [System.Net.CredentialCache]::DefaultCredentials + $wc.Proxy = $proxy + return $wc +} + +Write-Host "Preparing to run build script..." + +if(!$PSScriptRoot){ + $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent +} + +$TOOLS_DIR = Join-Path $PSScriptRoot "tools" +$ADDINS_DIR = Join-Path $TOOLS_DIR "Addins" +$MODULES_DIR = Join-Path $TOOLS_DIR "Modules" +$NUGET_EXE = Join-Path $TOOLS_DIR "nuget.exe" +$CAKE_EXE = Join-Path $TOOLS_DIR "Cake/Cake.exe" +$NUGET_URL = "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe" +$PACKAGES_CONFIG = Join-Path $TOOLS_DIR "packages.config" +$PACKAGES_CONFIG_MD5 = Join-Path $TOOLS_DIR "packages.config.md5sum" +$ADDINS_PACKAGES_CONFIG = Join-Path $ADDINS_DIR "packages.config" +$MODULES_PACKAGES_CONFIG = Join-Path $MODULES_DIR "packages.config" + +# Make sure tools folder exists +if ((Test-Path $PSScriptRoot) -and !(Test-Path $TOOLS_DIR)) { + Write-Verbose -Message "Creating tools directory..." + New-Item -Path $TOOLS_DIR -Type directory | out-null +} + +# Make sure that packages.config exist. +if (!(Test-Path $PACKAGES_CONFIG)) { + Write-Verbose -Message "Downloading packages.config..." + try { + $wc = GetProxyEnabledWebClient + $wc.DownloadFile("https://cakebuild.net/download/bootstrapper/packages", $PACKAGES_CONFIG) } catch { + Throw "Could not download packages.config." + } +} + +# Try find NuGet.exe in path if not exists +if (!(Test-Path $NUGET_EXE)) { + Write-Verbose -Message "Trying to find nuget.exe in PATH..." + $existingPaths = $Env:Path -Split ';' | Where-Object { (![string]::IsNullOrEmpty($_)) -and (Test-Path $_ -PathType Container) } + $NUGET_EXE_IN_PATH = Get-ChildItem -Path $existingPaths -Filter "nuget.exe" | Select -First 1 + if ($NUGET_EXE_IN_PATH -ne $null -and (Test-Path $NUGET_EXE_IN_PATH.FullName)) { + Write-Verbose -Message "Found in PATH at $($NUGET_EXE_IN_PATH.FullName)." + $NUGET_EXE = $NUGET_EXE_IN_PATH.FullName + } +} + +# Try download NuGet.exe if not exists +if (!(Test-Path $NUGET_EXE)) { + Write-Verbose -Message "Downloading NuGet.exe..." + try { + $wc = GetProxyEnabledWebClient + $wc.DownloadFile($NUGET_URL, $NUGET_EXE) + } catch { + Throw "Could not download NuGet.exe." + } +} + +# Save nuget.exe path to environment to be available to child processed +$ENV:NUGET_EXE = $NUGET_EXE + +# Restore tools from NuGet? +if(-Not $SkipToolPackageRestore.IsPresent) { + Push-Location + Set-Location $TOOLS_DIR + + # Check for changes in packages.config and remove installed tools if true. + [string] $md5Hash = MD5HashFile($PACKAGES_CONFIG) + if((!(Test-Path $PACKAGES_CONFIG_MD5)) -Or + ($md5Hash -ne (Get-Content $PACKAGES_CONFIG_MD5 ))) { + Write-Verbose -Message "Missing or changed package.config hash..." + Remove-Item * -Recurse -Exclude packages.config,nuget.exe + } + + Write-Verbose -Message "Restoring tools from NuGet..." + $NuGetOutput = Invoke-Expression "&`"$NUGET_EXE`" install -ExcludeVersion -OutputDirectory `"$TOOLS_DIR`"" + + if ($LASTEXITCODE -ne 0) { + Throw "An error occurred while restoring NuGet tools." + } + else + { + $md5Hash | Out-File $PACKAGES_CONFIG_MD5 -Encoding "ASCII" + } + Write-Verbose -Message ($NuGetOutput | out-string) + + Pop-Location +} + +# Restore addins from NuGet +if (Test-Path $ADDINS_PACKAGES_CONFIG) { + Push-Location + Set-Location $ADDINS_DIR + + Write-Verbose -Message "Restoring addins from NuGet..." + $NuGetOutput = Invoke-Expression "&`"$NUGET_EXE`" install -ExcludeVersion -OutputDirectory `"$ADDINS_DIR`"" + + if ($LASTEXITCODE -ne 0) { + Throw "An error occurred while restoring NuGet addins." + } + + Write-Verbose -Message ($NuGetOutput | out-string) + + Pop-Location +} + +# Restore modules from NuGet +if (Test-Path $MODULES_PACKAGES_CONFIG) { + Push-Location + Set-Location $MODULES_DIR + + Write-Verbose -Message "Restoring modules from NuGet..." + $NuGetOutput = Invoke-Expression "&`"$NUGET_EXE`" install -ExcludeVersion -OutputDirectory `"$MODULES_DIR`"" + + if ($LASTEXITCODE -ne 0) { + Throw "An error occurred while restoring NuGet modules." + } + + Write-Verbose -Message ($NuGetOutput | out-string) + + Pop-Location +} + +# Make sure that Cake has been installed. +if (!(Test-Path $CAKE_EXE)) { + Throw "Could not find Cake.exe at $CAKE_EXE" +} + + + +# Build Cake arguments +$cakeArguments = @("$Script"); +if ($Target) { $cakeArguments += "-target=$Target" } +if ($Configuration) { $cakeArguments += "-configuration=$Configuration" } +if ($Verbosity) { $cakeArguments += "-verbosity=$Verbosity" } +if ($ShowDescription) { $cakeArguments += "-showdescription" } +if ($DryRun) { $cakeArguments += "-dryrun" } +if ($Experimental) { $cakeArguments += "-experimental" } +if ($Mono) { $cakeArguments += "-mono" } +$cakeArguments += $ScriptArgs + +# Start Cake +Write-Host "Running build script..." +&$CAKE_EXE $cakeArguments +exit $LASTEXITCODE diff --git a/build.sh b/build.sh new file mode 100644 index 0000000000000000000000000000000000000000..d088917ed78538ff57cf654cf71aad6bf045d655 --- /dev/null +++ b/build.sh @@ -0,0 +1,122 @@ +#!/usr/bin/env bash + +#The MIT License (MIT) +# +#Copyright (c) 2014 - 2016 Patrik Svensson, Mattias Karlsson, Gary Ewan Park and contributors +# +#Permission is hereby granted, free of charge, to any person obtaining a copy of +#this software and associated documentation files (the "Software"), to deal in +#the Software without restriction, including without limitation the rights to +#use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +#the Software, and to permit persons to whom the Software is furnished to do so, +#subject to the following conditions: +# +#The above copyright notice and this permission notice shall be included in all +#copies or substantial portions of the Software. +# +#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +#FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +#COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +#IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +#CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +########################################################################## +# This is the Cake bootstrapper script for Linux and OS X. +# This file was downloaded from https://github.com/cake-build/resources +# Feel free to change this file to fit your needs. +########################################################################## + +# Define directories. +SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) +TOOLS_DIR=$SCRIPT_DIR/tools +NUGET_EXE=$TOOLS_DIR/nuget.exe +CAKE_EXE=$TOOLS_DIR/Cake/Cake.exe +PACKAGES_CONFIG=$TOOLS_DIR/packages.config +PACKAGES_CONFIG_MD5=$TOOLS_DIR/packages.config.md5sum + +# Define md5sum or md5 depending on Linux/OSX +MD5_EXE= +if [[ "$(uname -s)" == "Darwin" ]]; then + MD5_EXE="md5 -r" +else + MD5_EXE="md5sum" +fi + +# Define default arguments. +SCRIPT="build.cake" +TARGET="Default" +CONFIGURATION="Release" +VERBOSITY="verbose" +DRYRUN= +SHOW_VERSION=false +SCRIPT_ARGUMENTS=() + +# Parse arguments. +for i in "$@"; do + case $1 in + -s|--script) SCRIPT="$2"; shift ;; + -t|--target) TARGET="$2"; shift ;; + -c|--configuration) CONFIGURATION="$2"; shift ;; + -v|--verbosity) VERBOSITY="$2"; shift ;; + -d|--dryrun) DRYRUN="-dryrun" ;; + --version) SHOW_VERSION=true ;; + --) shift; SCRIPT_ARGUMENTS+=("$@"); break ;; + *) SCRIPT_ARGUMENTS+=("$1") ;; + esac + shift +done + +# Make sure the tools folder exist. +if [ ! -d "$TOOLS_DIR" ]; then + mkdir "$TOOLS_DIR" +fi + +# Make sure that packages.config exist. +if [ ! -f "$TOOLS_DIR/packages.config" ]; then + echo "Downloading packages.config..." + curl -Lsfo "$TOOLS_DIR/packages.config" https://cakebuild.net/download/bootstrapper/packages + if [ $? -ne 0 ]; then + echo "An error occurred while downloading packages.config." + exit 1 + fi +fi + +# Download NuGet if it does not exist. +if [ ! -f "$NUGET_EXE" ]; then + echo "Downloading NuGet..." + curl -Lsfo "$NUGET_EXE" https://dist.nuget.org/win-x86-commandline/latest/nuget.exe + if [ $? -ne 0 ]; then + echo "An error occurred while downloading nuget.exe." + exit 1 + fi +fi + +# Restore tools from NuGet. +pushd "$TOOLS_DIR" >/dev/null +if [ ! -f $PACKAGES_CONFIG_MD5 ] || [ "$( cat $PACKAGES_CONFIG_MD5 | sed 's/\r$//' )" != "$( $MD5_EXE $PACKAGES_CONFIG | awk '{ print $1 }' )" ]; then + find . -type d ! -name . | xargs rm -rf +fi + +mono "$NUGET_EXE" install -ExcludeVersion +if [ $? -ne 0 ]; then + echo "Could not restore NuGet packages." + exit 1 +fi + +$MD5_EXE $PACKAGES_CONFIG | awk '{ print $1 }' >| $PACKAGES_CONFIG_MD5 + +popd >/dev/null + +# Make sure that Cake has been installed. +if [ ! -f "$CAKE_EXE" ]; then + echo "Could not find Cake.exe at '$CAKE_EXE'." + exit 1 +fi + +# Start Cake +if $SHOW_VERSION; then + exec mono "$CAKE_EXE" -version +else + exec mono "$CAKE_EXE" $SCRIPT -verbosity=$VERBOSITY -configuration=$CONFIGURATION -target=$TARGET $DRYRUN "${SCRIPT_ARGUMENTS[@]}" +fi \ No newline at end of file diff --git a/nunit3-junit.xslt b/nunit3-junit.xslt new file mode 100644 index 0000000000000000000000000000000000000000..bf69bdb1d2cd6fc2fdbeb915b4eb6732f720848e --- /dev/null +++ b/nunit3-junit.xslt @@ -0,0 +1,71 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Taken from: https://github.com/nunit/nunit-transforms/tree/master/nunit3-junit +--> +<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> + <xsl:output method="xml" indent="yes"/> + + <xsl:template match="/test-run"> + <testsuites tests="{@testcasecount}" failures="{@failed}" disabled="{@skipped}" time="{@duration}"> + <xsl:apply-templates/> + </testsuites> + </xsl:template> + + <xsl:template match="test-suite"> + <xsl:if test="test-case"> + <testsuite tests="{@testcasecount}" time="{@duration}" errors="{@testcasecount - @passed - @skipped - @failed}" failures="{@failed}" skipped="{@skipped}" timestamp="{@start-time}"> + <xsl:attribute name="name"> + <xsl:for-each select="ancestor-or-self::test-suite/@name"> + <xsl:value-of select="concat(., '.')"/> + </xsl:for-each> + </xsl:attribute> + <xsl:apply-templates select="test-case"/> + </testsuite> + <xsl:apply-templates select="test-suite"/> + </xsl:if> + <xsl:if test="not(test-case)"> + <xsl:apply-templates/> + </xsl:if> + </xsl:template> + + <xsl:template match="test-case"> + <testcase name="{@name}" assertions="{@asserts}" time="{@duration}" status="{@result}" classname="{@classname}"> + <xsl:if test="@runstate = 'Skipped' or @runstate = 'Ignored'"> + <skipped/> + </xsl:if> + + <xsl:apply-templates/> + </testcase> + </xsl:template> + + <xsl:template match="command-line"/> + <xsl:template match="settings"/> + + <xsl:template match="output"> + <system-out> + <xsl:value-of select="."/> + </system-out> + </xsl:template> + + <xsl:template match="stack-trace"> + </xsl:template> + + <xsl:template match="test-case/failure"> + <failure message="{./message}"> + <xsl:value-of select="./stack-trace"/> + </failure> + </xsl:template> + + <xsl:template match="test-suite/failure"/> + + <xsl:template match="test-case/reason"> + <skipped message="{./message}"/> + </xsl:template> + + <xsl:template match="test-case/assertions"> + </xsl:template> + + <xsl:template match="test-suite/reason"/> + + <xsl:template match="properties"/> +</xsl:stylesheet> \ No newline at end of file diff --git a/src/KpiGenerator.sln b/src/KpiGenerator.sln new file mode 100644 index 0000000000000000000000000000000000000000..0a3ff8558f5f587c17470a2361913351c7cab28e --- /dev/null +++ b/src/KpiGenerator.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30413.136 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KpiGenerator", "KpiGenerator\KpiGenerator.csproj", "{009557C6-E057-4524-8037-821C4445B2D4}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {009557C6-E057-4524-8037-821C4445B2D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {009557C6-E057-4524-8037-821C4445B2D4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {009557C6-E057-4524-8037-821C4445B2D4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {009557C6-E057-4524-8037-821C4445B2D4}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {594F2ED9-B7AE-4CE6-B319-F08DAF6329A6} + EndGlobalSection +EndGlobal diff --git a/src/KpiGenerator/App.config b/src/KpiGenerator/App.config new file mode 100644 index 0000000000000000000000000000000000000000..7039cbe2788b9da5837c73c79ad949fc73511498 --- /dev/null +++ b/src/KpiGenerator/App.config @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8"?> +<configuration> + <configSections> + <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 --> + <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" /> + </configSections> + <startup> + <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" /> + </startup> + <entityFramework> + <providers> + <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" /> + </providers> + </entityFramework> + <runtime> + <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> + <dependentAssembly> + <assemblyIdentity name="linq2db" publicKeyToken="e41013125f9e410a" culture="neutral" /> + <bindingRedirect oldVersion="0.0.0.0-3.1.1.0" newVersion="3.1.1.0" /> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="dotNetRDF" publicKeyToken="6055ffe4c97cc780" culture="neutral" /> + <bindingRedirect oldVersion="0.0.0.0-2.6.0.0" newVersion="2.6.0.0" /> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="Coscine.Database" publicKeyToken="767d77427707b70a" culture="neutral" /> + <bindingRedirect oldVersion="0.0.0.0-1.26.0.0" newVersion="1.26.0.0" /> + </dependentAssembly> + </assemblyBinding> + </runtime> +</configuration> diff --git a/src/KpiGenerator/Generators/GenerateProjectsPerIkz.cs b/src/KpiGenerator/Generators/GenerateProjectsPerIkz.cs new file mode 100644 index 0000000000000000000000000000000000000000..c50e3a8d5529f3b01afeff3bfb738e2b9850148e --- /dev/null +++ b/src/KpiGenerator/Generators/GenerateProjectsPerIkz.cs @@ -0,0 +1,59 @@ +using Coscine.Configuration; +using Coscine.Database.DataModel; +using Coscine.Database.Models; +using Coscine.Database.Util; +using Coscine.Metadata; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Coscine.KpiGenerator.Generators +{ + class GenerateProjectsPerIkz : KpiGenerator + { + public GenerateProjectsPerIkz(IConfiguration configuration, string measurementID) : base(configuration, measurementID) + { + } + + public override List<Kpi> GenerateKpis() + { + var rdfStoreConnector = new RdfStoreConnector(_configuration.GetStringAndWait("coscine/local/virtuoso/additional/url")); + var organizationToIkzDict = rdfStoreConnector.GetOrganizationToIkzMap(); + var projectModel = new ProjectModel(); + + var result = new List<Kpi>(); + + var orgForProjects = projectModel.GetProjectCountByOrganization(); + + var countForeignOrganizations = 0; + var countRawRWTHOrganizations = 0; + foreach (var r in orgForProjects) + { + if (r.Url == null) + { + continue; + } + if (organizationToIkzDict.ContainsKey(r.Url)) + { + result.Add(CreateKpi(organizationToIkzDict[r.Url], r.Count)); + } + else + { + if (r.Url == "https://ror.org/04xfq0f34") + { + countRawRWTHOrganizations += r.Count; + } + else + { + countForeignOrganizations += r.Count; + } + } + } + result.Add(CreateKpi("000000", countForeignOrganizations)); + result.Add(CreateKpi("000001", countRawRWTHOrganizations)); + return result; + } + } +} diff --git a/src/KpiGenerator/Generators/GenerateRDSBucketsPerIkz.cs b/src/KpiGenerator/Generators/GenerateRDSBucketsPerIkz.cs new file mode 100644 index 0000000000000000000000000000000000000000..4bfa0bc3c554d329d174d5cda1dd39cac078192d --- /dev/null +++ b/src/KpiGenerator/Generators/GenerateRDSBucketsPerIkz.cs @@ -0,0 +1,59 @@ +using Coscine.Configuration; +using Coscine.Database.DataModel; +using Coscine.Database.Models; +using Coscine.Database.Util; +using Coscine.Metadata; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Coscine.KpiGenerator.Generators +{ + class GenerateRDSBucketsPerIkz : KpiGenerator + { + public GenerateRDSBucketsPerIkz(IConfiguration configuration, string measurementID) : base(configuration, measurementID) + { + } + + public override List<Kpi> GenerateKpis() + { + var rdfStoreConnector = new RdfStoreConnector(_configuration.GetStringAndWait("coscine/local/virtuoso/additional/url")); + var organizationToIkzDict = rdfStoreConnector.GetOrganizationToIkzMap(); + var resourceModel = new ResourceModel(); + + var result = new List<Kpi>(); + + var bucketForProjects = resourceModel.GetRDSBucketCountByOrganization(); + + var countForeignOrganizations = 0; + var countRawRWTHOrganizations = 0; + foreach (var r in bucketForProjects) + { + if (r.Url == null) + { + continue; + } + if (organizationToIkzDict.ContainsKey(r.Url)) + { + result.Add(CreateKpi(organizationToIkzDict[r.Url], r.Count)); + } + else + { + if (r.Url == "https://ror.org/04xfq0f34") + { + countRawRWTHOrganizations += r.Count; + } + else + { + countForeignOrganizations += r.Count; + } + } + } + result.Add(CreateKpi("000000", countForeignOrganizations)); + result.Add(CreateKpi("000001", countRawRWTHOrganizations)); + return result; + } + } +} diff --git a/src/KpiGenerator/Generators/GenerateRDSQuotasPerIkz.cs b/src/KpiGenerator/Generators/GenerateRDSQuotasPerIkz.cs new file mode 100644 index 0000000000000000000000000000000000000000..32ad835289e2db27ed4e488379eaf56b9f71cfde --- /dev/null +++ b/src/KpiGenerator/Generators/GenerateRDSQuotasPerIkz.cs @@ -0,0 +1,80 @@ +using Amazon.S3; +using Amazon.S3.Model; +using Coscine.Configuration; +using Coscine.Database.DataModel; +using Coscine.Database.Models; +using Coscine.Database.Util; +using Coscine.Metadata; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Coscine.KpiGenerator.Generators +{ + class GenerateRDSQuotasPerIkz : KpiGenerator + { + public GenerateRDSQuotasPerIkz(IConfiguration configuration, string measurementID) : base(configuration, measurementID) + { + } + + public override List<Kpi> GenerateKpis() + { + var rdfStoreConnector = new RdfStoreConnector(_configuration.GetStringAndWait("coscine/local/virtuoso/additional/url")); + var organizationToIkzDict = rdfStoreConnector.GetOrganizationToIkzMap(); + var rdsResourceTypeModel = new RDSResourceTypeModel(); + var resourceModel = new ResourceModel(); + + var result = new List<Kpi>(); + + var bucketForProjects = resourceModel.GetRDSResourceListByOrganization(); + + var dictQuota = new Dictionary<string, double>(); + + var countForeignOrganizations = 0.0; + var countRawRWTHOrganizations = 0.0; + foreach (var res in bucketForProjects) + { + if (res.Url == null) + { + continue; + } + foreach (var r in res.Resources) + { + var rdsResourceType = rdsResourceTypeModel.GetById(resourceModel.GetById(r.Id).ResourceTypeOptionId.Value); + var bucketname = rdsResourceType.BucketName; + + var subject = res.Url; + if (dictQuota.ContainsKey(subject)) + { + dictQuota[subject] = dictQuota[subject] + (int)(rdsResourceType.Size); + } + else if (subject.Contains("https://ror.org/04xfq0f34#")) + { + dictQuota.Add(subject, (int)(rdsResourceType.Size)); + } + else if (subject == "https://ror.org/04xfq0f34") + { + countRawRWTHOrganizations += (int)(rdsResourceType.Size); + } + else + { + countForeignOrganizations += (int)(rdsResourceType.Size); + } + } + } + + foreach (var quota in dictQuota) + { + if (organizationToIkzDict.ContainsKey(quota.Key)) + { + result.Add(CreateKpi(organizationToIkzDict[quota.Key], dictQuota[quota.Key])); + } + } + result.Add(CreateKpi("000000", countForeignOrganizations)); + result.Add(CreateKpi("000001", countRawRWTHOrganizations)); + return result; + } + } +} diff --git a/src/KpiGenerator/Generators/GenerateUsersPerIkz.cs b/src/KpiGenerator/Generators/GenerateUsersPerIkz.cs new file mode 100644 index 0000000000000000000000000000000000000000..166530efc1e5869859ea7d3cdb033c25dc4f9821 --- /dev/null +++ b/src/KpiGenerator/Generators/GenerateUsersPerIkz.cs @@ -0,0 +1,106 @@ +using Coscine.Configuration; +using Coscine.Database.DataModel; +using Coscine.Database.Models; +using Coscine.Database.Util; +using Coscine.Metadata; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Coscine.KpiGenerator.Generators +{ + class GenerateUsersPerIkz : KpiGenerator + { + public GenerateUsersPerIkz(IConfiguration configuration, string measurementID) : base(configuration, measurementID) + { + } + + public override List<Kpi> GenerateKpis() + { + var externalIdModel = new ExternalIdModel(); + var rdfStoreConnector = new RdfStoreConnector(_configuration.GetStringAndWait("coscine/local/virtuoso/additional/url")); + var organizationToIkzDict = rdfStoreConnector.GetOrganizationToIkzMap(); + + var dictUser = new Dictionary<string, int>(); + var userModel = new UserModel(); + + var result = new List<Kpi>(); + + var allUsersThatAcceptedTOS = userModel.GetActiveUserIds(); + + var countForeignOrganizations = 0; + var countRawRWTHOrganizations = 0; + foreach (var userId in allUsersThatAcceptedTOS) + { + var externalIds = externalIdModel.GetAllWhere((externalId) => externalId.UserId == userId); + var externalIdList = new List<string>(); + foreach (var externalId in externalIds) + { + externalIdList.Add(externalId.ExternalIdColumn); + } + var memberData = rdfStoreConnector.GetTriples(new Uri("https://ror.org/04xfq0f34"), null, null, 1, externalIdList); + + // data available in virtuoso + if (memberData.Count() != 0) + { + foreach (var member in memberData) + { + var subject = member.Subject.ToString(); + if (dictUser.ContainsKey(subject)) + { + dictUser[subject] = dictUser[subject] + 1; + } + else + { + dictUser.Add(subject, 1); + } + } + } + else + { + var user = userModel.GetById(userId); + if (user.Institute != null) + { + if (dictUser.ContainsKey(user.Institute)) + { + dictUser[user.Institute] += 1; + } + else + { + dictUser.Add(user.Institute, 1); + } + } + } + } + + + foreach (var user in dictUser) + { + if (dictUser.ContainsKey("https://ror.org/04xfq0f34")) + { + countRawRWTHOrganizations += dictUser["https://ror.org/04xfq0f34"]; + } + else if (organizationToIkzDict.ContainsKey(user.Key)) + { + result.Add(new Kpi() + { + MeasurementID = _measurementID, + Ikz = organizationToIkzDict[user.Key], + Value = dictUser[user.Key], + Start = DateTime.UtcNow + }); + } + else + { + countForeignOrganizations += dictUser[user.Key]; + } + } + + result.Add(CreateKpi("000000", countForeignOrganizations)); + result.Add(CreateKpi("000001", countRawRWTHOrganizations)); + return result; + } + } +} diff --git a/src/KpiGenerator/KpiGenerator.cs b/src/KpiGenerator/KpiGenerator.cs new file mode 100644 index 0000000000000000000000000000000000000000..57e70019a85744b70cebdb0eb6abd166a10f1777 --- /dev/null +++ b/src/KpiGenerator/KpiGenerator.cs @@ -0,0 +1,35 @@ +using Coscine.Configuration; +using Coscine.Database.DataModel; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Coscine.KpiGenerator +{ + abstract class KpiGenerator + { + protected IConfiguration _configuration; + protected string _measurementID; + + public KpiGenerator(IConfiguration configuration, string measurementID) + { + _configuration = configuration; + _measurementID = measurementID; + } + + public abstract List<Kpi> GenerateKpis(); + + public Kpi CreateKpi(string ikz, double value) + { + return new Kpi() + { + MeasurementID = _measurementID, + Ikz = ikz, + Value = value, + Start = DateTime.UtcNow + }; + } + } +} diff --git a/src/KpiGenerator/KpiGenerator.csproj b/src/KpiGenerator/KpiGenerator.csproj new file mode 100644 index 0000000000000000000000000000000000000000..a7cc124d857c8e27856bd5e62826237c342162be --- /dev/null +++ b/src/KpiGenerator/KpiGenerator.csproj @@ -0,0 +1,134 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="..\packages\EntityFramework.6.4.4\build\EntityFramework.props" Condition="Exists('..\packages\EntityFramework.6.4.4\build\EntityFramework.props')" /> + <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{009557C6-E057-4524-8037-821C4445B2D4}</ProjectGuid> + <OutputType>Exe</OutputType> + <RootNamespace>Coscine.KpiGenerator</RootNamespace> + <AssemblyName>Coscine.KpiGenerator</AssemblyName> + <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> + <Deterministic>true</Deterministic> + <NuGetPackageImportStamp> + </NuGetPackageImportStamp> + <TargetFrameworkProfile /> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <PlatformTarget>AnyCPU</PlatformTarget> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <PlatformTarget>AnyCPU</PlatformTarget> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="AWSSDK.Core, Version=3.3.0.0, Culture=neutral, PublicKeyToken=885c28607f98e604, processorArchitecture=MSIL"> + <HintPath>..\packages\AWSSDK.Core.3.5.1.32\lib\net45\AWSSDK.Core.dll</HintPath> + </Reference> + <Reference Include="AWSSDK.S3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=885c28607f98e604, processorArchitecture=MSIL"> + <HintPath>..\packages\AWSSDK.S3.3.5.3.10\lib\net45\AWSSDK.S3.dll</HintPath> + </Reference> + <Reference Include="Consul, Version=0.7.2.6, Culture=neutral, PublicKeyToken=20a6ad9a81df1d95, processorArchitecture=MSIL"> + <HintPath>..\packages\Consul.0.7.2.6\lib\net45\Consul.dll</HintPath> + </Reference> + <Reference Include="Coscine.Configuration, Version=1.5.0.0, Culture=neutral, PublicKeyToken=ce3d7a32d7dc1e5a, processorArchitecture=MSIL"> + <HintPath>..\packages\Coscine.Configuration.1.5.0\lib\net461\Coscine.Configuration.dll</HintPath> + </Reference> + <Reference Include="Coscine.Database, Version=1.26.0.0, Culture=neutral, PublicKeyToken=767d77427707b70a, processorArchitecture=MSIL"> + <HintPath>..\packages\Coscine.Database.1.26.0\lib\net461\Coscine.Database.dll</HintPath> + </Reference> + <Reference Include="Coscine.Database.T4, Version=1.26.0.0, Culture=neutral, PublicKeyToken=84b4c404a0696261, processorArchitecture=MSIL"> + <HintPath>..\packages\Coscine.Database.1.26.0\lib\net461\Coscine.Database.T4.dll</HintPath> + </Reference> + <Reference Include="Coscine.Metadata, Version=1.4.0.0, Culture=neutral, processorArchitecture=MSIL"> + <HintPath>..\packages\Coscine.Metadata.1.4.0\lib\net461\Coscine.Metadata.dll</HintPath> + </Reference> + <Reference Include="dotNetRDF, Version=2.6.0.0, Culture=neutral, PublicKeyToken=6055ffe4c97cc780, processorArchitecture=MSIL"> + <HintPath>..\packages\dotNetRDF.2.6.0\lib\net40\dotNetRDF.dll</HintPath> + </Reference> + <Reference Include="dotNetRDF.Data.Virtuoso, Version=2.6.0.0, Culture=neutral, PublicKeyToken=6055ffe4c97cc780, processorArchitecture=MSIL"> + <HintPath>..\packages\dotNetRDF.Data.Virtuoso.2.6.0\lib\net40\dotNetRDF.Data.Virtuoso.dll</HintPath> + </Reference> + <Reference Include="EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL"> + <HintPath>..\packages\EntityFramework.6.4.4\lib\net45\EntityFramework.dll</HintPath> + </Reference> + <Reference Include="EntityFramework.SqlServer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL"> + <HintPath>..\packages\EntityFramework.6.4.4\lib\net45\EntityFramework.SqlServer.dll</HintPath> + </Reference> + <Reference Include="HtmlAgilityPack, Version=1.11.24.0, Culture=neutral, PublicKeyToken=bd319b19eaf3b43a, processorArchitecture=MSIL"> + <HintPath>..\packages\HtmlAgilityPack.1.11.24\lib\Net45\HtmlAgilityPack.dll</HintPath> + </Reference> + <Reference Include="linq2db, Version=3.1.1.0, Culture=neutral, PublicKeyToken=e41013125f9e410a, processorArchitecture=MSIL"> + <HintPath>..\packages\linq2db.3.1.1\lib\net46\linq2db.dll</HintPath> + </Reference> + <Reference Include="LinqKit, Version=1.1.17.0, Culture=neutral, PublicKeyToken=bc217f8844052a91, processorArchitecture=MSIL"> + <HintPath>..\packages\LinqKit.1.1.17\lib\net45\LinqKit.dll</HintPath> + </Reference> + <Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> + <HintPath>..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll</HintPath> + </Reference> + <Reference Include="System" /> + <Reference Include="System.Collections.NonGeneric, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\System.Collections.NonGeneric.4.3.0\lib\net46\System.Collections.NonGeneric.dll</HintPath> + </Reference> + <Reference Include="System.ComponentModel.DataAnnotations" /> + <Reference Include="System.Configuration" /> + <Reference Include="System.Core" /> + <Reference Include="System.Net.Http.WebRequest" /> + <Reference Include="System.Security" /> + <Reference Include="System.Web" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="System.Data.DataSetExtensions" /> + <Reference Include="Microsoft.CSharp" /> + <Reference Include="System.Data" /> + <Reference Include="System.Net.Http" /> + <Reference Include="System.Xml" /> + <Reference Include="VDS.Common, Version=1.10.0.0, Culture=neutral, PublicKeyToken=ab5f4eb908061bf0, processorArchitecture=MSIL"> + <HintPath>..\packages\VDS.Common.1.10.0\lib\net40-client\VDS.Common.dll</HintPath> + </Reference> + <Reference Include="virtado4, Version=4.0.0.0, Culture=neutral, PublicKeyToken=391bf132017ae989, processorArchitecture=MSIL"> + <HintPath>..\packages\OpenLink.Data.Virtuoso.7.20.3214.1\lib\net40\virtado4.dll</HintPath> + </Reference> + </ItemGroup> + <ItemGroup> + <Compile Include="Generators\GenerateRDSQuotasPerIkz.cs" /> + <Compile Include="Generators\GenerateProjectsPerIkz.cs" /> + <Compile Include="Generators\GenerateRDSBucketsPerIkz.cs" /> + <Compile Include="Generators\GenerateUsersPerIkz.cs" /> + <Compile Include="KpiGenerator.cs" /> + <Compile Include="Program.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="Reporter\HamsterReporter.cs" /> + </ItemGroup> + <ItemGroup> + <None Include="App.config" /> + <None Include="packages.config" /> + </ItemGroup> + <ItemGroup> + <Analyzer Include="..\packages\AWSSDK.S3.3.5.3.10\analyzers\dotnet\cs\AWSSDK.S3.CodeAnalysis.dll" /> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> + <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> + <PropertyGroup> + <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText> + </PropertyGroup> + <Error Condition="!Exists('..\packages\EntityFramework.6.4.4\build\EntityFramework.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\EntityFramework.6.4.4\build\EntityFramework.props'))" /> + <Error Condition="!Exists('..\packages\EntityFramework.6.4.4\build\EntityFramework.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\EntityFramework.6.4.4\build\EntityFramework.targets'))" /> + </Target> + <Import Project="..\packages\EntityFramework.6.4.4\build\EntityFramework.targets" Condition="Exists('..\packages\EntityFramework.6.4.4\build\EntityFramework.targets')" /> +</Project> \ No newline at end of file diff --git a/src/KpiGenerator/Program.cs b/src/KpiGenerator/Program.cs new file mode 100644 index 0000000000000000000000000000000000000000..f5172c359e83e41712491c445f89e8c0438f6d56 --- /dev/null +++ b/src/KpiGenerator/Program.cs @@ -0,0 +1,55 @@ +using Coscine.Configuration; +using Coscine.Database.Settings; +using Coscine.Database.Models; +using LinqToDB.Data; +using System; +using System.Collections.Generic; +using VDS.RDF.Storage; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Coscine.Metadata; +using Coscine.KpiGenerator.Reporter; +using Coscine.KpiGenerator.Generators; +using Coscine.Database.DataModel; + +namespace Coscine.KpiGenerator +{ + class Program + { + static void Main(string[] args) + { + ConsulConfiguration configuration = new ConsulConfiguration(); + DataConnection.DefaultSettings = new CoscineSettings(configuration); + + // Run all Generators for the KPI + // each Generator returns a list of KPI, it can have zero entries. + List<Kpi> newKpis = new List<Kpi>(); + newKpis.AddRange(new GenerateProjectsPerIkz(configuration, "2969").GenerateKpis()); + newKpis.AddRange(new GenerateRDSBucketsPerIkz(configuration, "2971").GenerateKpis()); + newKpis.AddRange(new GenerateRDSQuotasPerIkz(configuration, "2973").GenerateKpis()); + newKpis.AddRange(new GenerateUsersPerIkz(configuration, "2967").GenerateKpis()); + + //when all generators are done + var kpiModel = new KpiModel(); + // each value is stored within the database + foreach (Kpi kpi in newKpis) + { + kpiModel.Insert(kpi); + } + + // get all values from the database that have not been successfully sent yet + var kpiToProcess = kpiModel.GetAllWhere((kpi) => (kpi.SentSuccessfully == false)).ToList(); + + // try to sent them as a bundle with the csv method + HamsterReporter hamsterReporter = new HamsterReporter(configuration); + hamsterReporter.Send(kpiToProcess); + + // if the kpi were sent successful mark all values within the database as successfully sent + foreach (Kpi kpi in kpiToProcess) + { + kpiModel.MarkAsSent(kpi); + } + } + } +} diff --git a/src/KpiGenerator/Properties/AssemblyInfo.cs b/src/KpiGenerator/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000000000000000000000000000000000..05ab20d445814b24cf49b9ef98d264bc59fc144c --- /dev/null +++ b/src/KpiGenerator/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// This code was generated by Cake. +// </auto-generated> +//------------------------------------------------------------------------------ +using System.Reflection; + +[assembly: AssemblyTitle("KpiGenerator")] +[assembly: AssemblyDescription("KpiGenerator is a part of the CoScInE group.")] +[assembly: AssemblyCompany("IT Center, RWTH Aachen University")] +[assembly: AssemblyProduct("KpiGenerator")] +[assembly: AssemblyVersion("1.0.0")] +[assembly: AssemblyFileVersion("1.0.0")] +[assembly: AssemblyInformationalVersion("1.0.0-topic-1051-basic0005")] +[assembly: AssemblyCopyright("2020 IT Center, RWTH Aachen University")] + diff --git a/src/KpiGenerator/Reporter/HamsterReporter.cs b/src/KpiGenerator/Reporter/HamsterReporter.cs new file mode 100644 index 0000000000000000000000000000000000000000..dd87b32f06433847613e5be1fcb5a5aacd365914 --- /dev/null +++ b/src/KpiGenerator/Reporter/HamsterReporter.cs @@ -0,0 +1,83 @@ +using Coscine.Configuration; +using Coscine.Database.DataModel; +using Newtonsoft.Json; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; + +namespace Coscine.KpiGenerator.Reporter +{ + class HamsterReporter + { + private readonly HttpClient httpClient; + private readonly string hamsterUrl = @"http://datahamster.itc.rwth-aachen.de/put.php"; + + private readonly string _name = "messdaten_lieferant"; + private readonly string _password = ""; + private readonly string _liveMode = "0"; + + public HamsterReporter(IConfiguration configuration) + { + _password = configuration.GetStringAndWait("coscine/global/reporting/password"); + _liveMode = configuration.GetStringAndWait("coscine/global/reporting/live"); + httpClient = new HttpClient(); + } + + /** + * Expects three parameters: + * login + * password + * csv + * Optional: + * debug + */ + public async void Send(List<Kpi> kpis) + { + var csv = ""; + for (var i = 0; i < kpis.Count; i++) + { + csv += FormatKpi(kpis[i]); + if (i < kpis.Count - 1) + { + csv += "|"; + } + } + + var values = $"login={_name}&password={_password}&csv={csv}"; + if (_liveMode != "1") + { + values += "&debug=1"; + } + + var content = JsonConvert.SerializeObject(values); + await SendData(content); + } + + private async Task<HttpResponseMessage> SendData(string data) + { + HttpContent content = new StringContent(data, Encoding.UTF8, "application/json"); + return await httpClient.PostAsync(hamsterUrl, content); + } + + private string FormatKpi(Kpi kpi) + { + return $"{kpi.MeasurementID};{kpi.Ikz};{FormatDate(kpi.Start)};{FormatDate(kpi.End)};{kpi.AdditionalInfo};{kpi.AdditionalInfo1};{kpi.AdditionalInfo2};{kpi.AdditionalInfo3};{kpi.AdditionalInfo4};{kpi.AdditionalInfo5};"; + } + + private string FormatDate(DateTime? date) + { + if(date == null) + { + return ""; + } + else + { + return ((DateTime) date).ToString("yyyy-MM-dd-HH-mm-ss"); + } + } + } +} diff --git a/src/KpiGenerator/packages.config b/src/KpiGenerator/packages.config new file mode 100644 index 0000000000000000000000000000000000000000..18d183e82745746b87a90310016ffc7fc02cc506 --- /dev/null +++ b/src/KpiGenerator/packages.config @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<packages> + <package id="AWSSDK.Core" version="3.5.1.32" targetFramework="net461" /> + <package id="AWSSDK.S3" version="3.5.3.10" targetFramework="net461" /> + <package id="Consul" version="0.7.2.6" targetFramework="net472" /> + <package id="Coscine.Configuration" version="1.5.0" targetFramework="net472" /> + <package id="Coscine.Database" version="1.26.0" targetFramework="net461" /> + <package id="Coscine.Metadata" version="1.4.0" targetFramework="net461" /> + <package id="dotNetRDF" version="2.6.0" targetFramework="net472" /> + <package id="dotNetRDF.Data.Virtuoso" version="2.6.0" targetFramework="net472" /> + <package id="EntityFramework" version="6.4.4" targetFramework="net472" /> + <package id="HtmlAgilityPack" version="1.11.24" targetFramework="net472" /> + <package id="linq2db" version="3.1.1" targetFramework="net472" /> + <package id="LinqKit" version="1.1.17" targetFramework="net472" /> + <package id="Newtonsoft.Json" version="12.0.3" targetFramework="net472" /> + <package id="OpenLink.Data.Virtuoso" version="7.20.3214.1" targetFramework="net472" /> + <package id="System.Collections.NonGeneric" version="4.3.0" targetFramework="net461" /> + <package id="VDS.Common" version="1.10.0" targetFramework="net472" /> +</packages> \ No newline at end of file diff --git a/tools/packages.config b/tools/packages.config new file mode 100644 index 0000000000000000000000000000000000000000..14aef3bf00189e621993b61ccea2e4a203e73b9b --- /dev/null +++ b/tools/packages.config @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<packages> + <package id="Cake" version="0.36.0" /> +</packages>