build: integrate with ob cicd and build templates

This commit is contained in:
Jonas Juselius
2022-10-04 11:35:42 +02:00
parent 85816bd692
commit a60017a2f8
51 changed files with 13736 additions and 60 deletions

73
.build/Build.fs Normal file
View File

@@ -0,0 +1,73 @@
open Fake.Core
open Fake.IO
open Farmer
open Farmer.Builders
open Helpers
initializeContext()
let srcPath = Path.getFullName "src"
let testPath = Path.getFullName "test"
let libPath = None
let distPath = Path.getFullName "dist"
let packPath = Path.getFullName "packages"
let versionFile = Path.getFullName ".version"
Target.create "Clean" (fun _ -> Shell.cleanDir distPath)
Target.create "InstallClient" (fun _ ->
run npm "install" "."
run dotnet "tool restore" "."
)
Target.create "Bundle" (fun _ ->
run dotnet $"publish -c Release -o {distPath}" srcPath
)
Target.create "BundleDebug" (fun _ ->
run dotnet $"publish -c Debug -o {distPath}" srcPath
)
Target.create "Pack" (fun _ ->
match libPath with
| Some p -> run dotnet $"pack -c Release -o {packPath}" p
| None -> ()
)
Target.create "Run" (fun _ -> run dotnet "watch run" srcPath)
Target.create "Format" (fun _ ->
run dotnet "fantomas . -r" "src"
)
Target.create "Test" (fun _ ->
if System.IO.Directory.Exists testPath then
run dotnet "run" testPath
else ()
)
open Fake.Core.TargetOperators
let dependencies = [
"Clean"
==> "InstallClient"
==> "Bundle"
"Clean"
==> "BundleDebug"
"Clean"
==> "Test"
"Clean"
==> "InstallClient"
==> "Run"
"Clean"
==> "Pack"
]
[<EntryPoint>]
let main args = runOrDefault args

105
.build/Helpers.fs Normal file
View File

@@ -0,0 +1,105 @@
module Helpers
open Fake.Core
let initializeContext () =
let execContext = Context.FakeExecutionContext.Create false "build.fsx" [ ]
Context.setExecutionContext (Context.RuntimeContext.Fake execContext)
module Proc =
module Parallel =
open System
let locker = obj()
let colors =
[| ConsoleColor.Blue
ConsoleColor.Yellow
ConsoleColor.Magenta
ConsoleColor.Cyan
ConsoleColor.DarkBlue
ConsoleColor.DarkYellow
ConsoleColor.DarkMagenta
ConsoleColor.DarkCyan |]
let print color (colored: string) (line: string) =
lock locker
(fun () ->
let currentColor = Console.ForegroundColor
Console.ForegroundColor <- color
Console.Write colored
Console.ForegroundColor <- currentColor
Console.WriteLine line)
let onStdout index name (line: string) =
let color = colors.[index % colors.Length]
if isNull line then
print color $"{name}: --- END ---" ""
else if String.isNotNullOrEmpty line then
print color $"{name}: " line
let onStderr name (line: string) =
let color = ConsoleColor.Red
if isNull line |> not then
print color $"{name}: " line
let redirect (index, (name, createProcess)) =
createProcess
|> CreateProcess.redirectOutputIfNotRedirected
|> CreateProcess.withOutputEvents (onStdout index name) (onStderr name)
let printStarting indexed =
for (index, (name, c: CreateProcess<_>)) in indexed do
let color = colors.[index % colors.Length]
let wd =
c.WorkingDirectory
|> Option.defaultValue ""
let exe = c.Command.Executable
let args = c.Command.Arguments.ToStartInfo
print color $"{name}: {wd}> {exe} {args}" ""
let run cs =
cs
|> Seq.toArray
|> Array.indexed
|> fun x -> printStarting x; x
|> Array.map redirect
|> Array.Parallel.map Proc.run
let createProcess exe arg dir =
CreateProcess.fromRawCommandLine exe arg
|> CreateProcess.withWorkingDirectory dir
|> CreateProcess.ensureExitCode
let dotnet = createProcess "dotnet"
let npm =
let npmPath =
match ProcessUtils.tryFindFileOnPath "npm" with
| Some path -> path
| None ->
"npm was not found in path. Please install it and make sure it's available from your path. " +
"See https://safe-stack.github.io/docs/quickstart/#install-pre-requisites for more info"
|> failwith
createProcess npmPath
let run proc arg dir =
proc arg dir
|> Proc.run
|> ignore
let runParallel processes =
processes
|> Proc.Parallel.run
|> ignore
let runOrDefault args =
try
match args with
| [| target |] -> Target.runOrDefault target
| _ ->
Target.runOrDefault "Run"
0
with e ->
printfn "%A" e
1

18
.config/dotnet-tools.json Normal file
View File

@@ -0,0 +1,18 @@
{
"version": 1,
"isRoot": true,
"tools": {
"fable": {
"version": "3.7.0",
"commands": [
"fable"
]
},
"fantomas-tool": {
"version": "4.6.4",
"commands": [
"fantomas"
]
}
}
}

29
.devcontainer/Dockerfile Normal file
View File

@@ -0,0 +1,29 @@
FROM mcr.microsoft.com/dotnet/sdk:6.0
# Add keys and sources lists
RUN curl -sL https://deb.nodesource.com/setup_14.x | bash
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" \
| tee /etc/apt/sources.list.d/yarn.list
# Install node, 7zip, yarn, git, process tools
RUN apt-get update \
&& apt-get install -y nodejs p7zip-full git procps ssh-client
# Clean up
RUN apt-get autoremove -y \
&& apt-get clean -y \
&& rm -rf /var/lib/apt/lists/*
# Install dotnet tools
RUN dotnet tool install fable -g
# Trouble brewing
RUN rm /etc/ssl/openssl.cnf
# add dotnet tools to path to pick up fake and paket installation
ENV PATH="/root/.dotnet/tools:${PATH}"
# Copy endpoint specific user settings into container to specify
# .NET Core should be used as the runtime.
COPY settings.vscode.json /root/.vscode-remote/data/Machine/settings.json

View File

@@ -0,0 +1,11 @@
{
"name": "SAFE",
"dockerFile": "Dockerfile",
"appPort": [8080, 8085],
"extensions": [
"ionide.ionide-fsharp",
"ms-dotnettools.csharp",
"editorconfig.editorconfig",
"msjsdiag.debugger-for-chrome"
]
}

View File

@@ -0,0 +1,3 @@
{
"FSharp.fsacRuntime":"netcore"
}

32
.editorconfig Normal file
View File

@@ -0,0 +1,32 @@
root = true
[*]
indent_style = space
indent_size = 4
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = false
[*.fs]
max_line_length=120
# Feliz style
fsharp_single_argument_web_mode=true
fsharp_space_before_colon=false
fsharp_max_if_then_else_short_width=60
fsharp_max_infix_operator_expression=50
fsharp_max_record_width=70
fsharp_max_record_number_of_items=1
fsharp_max_array_or_list_width=70
fsharp_max_array_or_list_number_of_items=1
fsharp_max_value_binding_width=70
fsharp_max_function_binding_width=40
fsharp_max_dot_get_expression_width=50
fsharp_multiline_block_brackets_on_same_column=true
fsharp_newline_between_type_definition_and_members=false
fsharp_max_elmish_width=40
fsharp_align_function_signature_to_indentation=false
fsharp_alternative_long_member_definitions=false
fsharp_multi_line_lambda_closing_newline=false
fsharp_disable_elmish_syntax=false
fsharp_keep_indent_in_branch=false
fsharp_blank_lines_around_nested_multiline_expressions=false

17
.gitignore vendored Normal file
View File

@@ -0,0 +1,17 @@
.fable/
.fake/
.vs/
obj/
bin/
packages/
node_modules/
src/Client/public/js/
release.cmd
release.sh
.idea/
*.orig
*.DotSettings.user
deploy
.ionide/
*.db
build.fsx.lock

8
.gitlab-ci.yml Normal file
View File

@@ -0,0 +1,8 @@
variables:
SKIP_TESTS: "true"
include:
- project: oceanbox/gitlab-ci
ref: main
file: Dotnet.gitlab-ci.yml

4
.gitmodules vendored Normal file
View File

@@ -0,0 +1,4 @@
[submodule "submodules/Oceanbox.FvcomKit"]
path = submodules/Oceanbox.FvcomKit
url = ../Oceanbox.FvcomKit
shallow = true

41
.releaserc.yaml Normal file
View File

@@ -0,0 +1,41 @@
branches:
- main
- master
- name: develop
prerelease: true
plugins:
- '@semantic-release/commit-analyzer'
- '@semantic-release/release-notes-generator'
- - '@semantic-release/changelog'
- changelogFile: RELEASE_NOTES.md
changelogTitle: "# Changelog"
- - 'semantic-release-dotnet'
- paths: [ "src/*.fsproj", "src/*/*.fsproj" ]
- - '@semantic-release/exec'
- generateNotesCmd: "echo ${nextRelease.version} > .version"
- - '@semantic-release/git'
- message: "chore(release): ${nextRelease.version}\n\n${nextRelease.notes}"
assets: [ "RELEASE_NOTES.md", ".version", "src/*.fsproj", "src/*/*.fsproj" ]
- - '@semantic-release/gitlab'
- assets: []
analyzeCommits:
- path: "@semantic-release/commit-analyzer"
releaseRules:
- type: "fix"
release: "patch"
- type: "patch"
release: "patch"
- type: "feat"
release: "minor"
- type: "feature"
release: "minor"
- type: "minor"
release: "minor"
- type: "breaking"
release: "major"
- type: "major"
release: "major"

16
Build.fsproj Normal file
View File

@@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Include=".build/Helpers.fs" />
<Compile Include=".build/Build.fs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Fake.Core.Target" Version="5.23.0" />
<PackageReference Include="Fake.DotNet.Cli" Version="5.23.0" />
<PackageReference Include="Fake.IO.FileSystem" Version="5.23.0" />
<PackageReference Include="Farmer" Version="1.7.10" />
</ItemGroup>
</Project>

7
Dockerfile Normal file
View File

@@ -0,0 +1,7 @@
FROM mcr.microsoft.com/dotnet/runtime:6.0
RUN rm /etc/ssl/openssl.cnf
COPY deploy/ /app
WORKDIR /app
CMD /app/FvcomStats

78
FvcomStats.sln Normal file
View File

@@ -0,0 +1,78 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27004.2005
MinimumVisualStudioVersion = 15.0.26124.0
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{984D61E1-48FB-4098-9019-C1E99B524F58}"
ProjectSection(SolutionItems) = preProject
README.md = README.md
LICENSE = LICENSE
Dockerfile = Dockerfile
.gitlab-ci.yml = .gitlab-ci.yml
EndProjectSection
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Build", "Build.fsproj", "{3E61AD37-F1A6-4B40-B466-A2B501321E2D}"
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "src", "src/FvcomStats.fsproj", "{C0576A34-91FA-49DA-97CE-3EBB7DFAA667}"
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "test", "test\Tests.fsproj", "{31724F29-E4E2-45C5-BB0D-1E2776D10A1A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{3E61AD37-F1A6-4B40-B466-A2B501321E2D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3E61AD37-F1A6-4B40-B466-A2B501321E2D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3E61AD37-F1A6-4B40-B466-A2B501321E2D}.Debug|x64.ActiveCfg = Debug|Any CPU
{3E61AD37-F1A6-4B40-B466-A2B501321E2D}.Debug|x64.Build.0 = Debug|Any CPU
{3E61AD37-F1A6-4B40-B466-A2B501321E2D}.Debug|x86.ActiveCfg = Debug|Any CPU
{3E61AD37-F1A6-4B40-B466-A2B501321E2D}.Debug|x86.Build.0 = Debug|Any CPU
{3E61AD37-F1A6-4B40-B466-A2B501321E2D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3E61AD37-F1A6-4B40-B466-A2B501321E2D}.Release|Any CPU.Build.0 = Release|Any CPU
{3E61AD37-F1A6-4B40-B466-A2B501321E2D}.Release|x64.ActiveCfg = Release|Any CPU
{3E61AD37-F1A6-4B40-B466-A2B501321E2D}.Release|x64.Build.0 = Release|Any CPU
{3E61AD37-F1A6-4B40-B466-A2B501321E2D}.Release|x86.ActiveCfg = Release|Any CPU
{3E61AD37-F1A6-4B40-B466-A2B501321E2D}.Release|x86.Build.0 = Release|Any CPU
{C0576A34-91FA-49DA-97CE-3EBB7DFAA667}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C0576A34-91FA-49DA-97CE-3EBB7DFAA667}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C0576A34-91FA-49DA-97CE-3EBB7DFAA667}.Debug|x64.ActiveCfg = Debug|Any CPU
{C0576A34-91FA-49DA-97CE-3EBB7DFAA667}.Debug|x64.Build.0 = Debug|Any CPU
{C0576A34-91FA-49DA-97CE-3EBB7DFAA667}.Debug|x86.ActiveCfg = Debug|Any CPU
{C0576A34-91FA-49DA-97CE-3EBB7DFAA667}.Debug|x86.Build.0 = Debug|Any CPU
{C0576A34-91FA-49DA-97CE-3EBB7DFAA667}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C0576A34-91FA-49DA-97CE-3EBB7DFAA667}.Release|Any CPU.Build.0 = Release|Any CPU
{C0576A34-91FA-49DA-97CE-3EBB7DFAA667}.Release|x64.ActiveCfg = Release|Any CPU
{C0576A34-91FA-49DA-97CE-3EBB7DFAA667}.Release|x64.Build.0 = Release|Any CPU
{C0576A34-91FA-49DA-97CE-3EBB7DFAA667}.Release|x86.ActiveCfg = Release|Any CPU
{C0576A34-91FA-49DA-97CE-3EBB7DFAA667}.Release|x86.Build.0 = Release|Any CPU
{31724F29-E4E2-45C5-BB0D-1E2776D10A1A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{31724F29-E4E2-45C5-BB0D-1E2776D10A1A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{31724F29-E4E2-45C5-BB0D-1E2776D10A1A}.Debug|x64.ActiveCfg = Debug|Any CPU
{31724F29-E4E2-45C5-BB0D-1E2776D10A1A}.Debug|x64.Build.0 = Debug|Any CPU
{31724F29-E4E2-45C5-BB0D-1E2776D10A1A}.Debug|x86.ActiveCfg = Debug|Any CPU
{31724F29-E4E2-45C5-BB0D-1E2776D10A1A}.Debug|x86.Build.0 = Debug|Any CPU
{31724F29-E4E2-45C5-BB0D-1E2776D10A1A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{31724F29-E4E2-45C5-BB0D-1E2776D10A1A}.Release|Any CPU.Build.0 = Release|Any CPU
{31724F29-E4E2-45C5-BB0D-1E2776D10A1A}.Release|x64.ActiveCfg = Release|Any CPU
{31724F29-E4E2-45C5-BB0D-1E2776D10A1A}.Release|x64.Build.0 = Release|Any CPU
{31724F29-E4E2-45C5-BB0D-1E2776D10A1A}.Release|x86.ActiveCfg = Release|Any CPU
{31724F29-E4E2-45C5-BB0D-1E2776D10A1A}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {2E1D05DC-0707-48E8-83A9-A7D8FA0A1E04}
EndGlobalSection
EndGlobal

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020 Serit Tromsø AS
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.

1
RELEASE_NOTES.md Normal file
View File

@@ -0,0 +1 @@
# Changelog

47
fvcomstats.def Normal file
View File

@@ -0,0 +1,47 @@
Bootstrap: docker
From: mcr.microsoft.com/dotnet/sdk:6.0
Stage: build
%files
. /build
~/.nuget/NuGet/NuGet.Config /build/NuGet.Config
%post
curl -sL https://deb.nodesource.com/setup_16.x | bash
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" \
| tee /etc/apt/sources.list.d/yarn.list
# Install node, 7zip, yarn, git, process tools
apt update \
&& apt install -y nodejs p7zip-full git procps ssh-client
# Clean up
apt autoremove -y \
&& apt clean -y \
&& rm -rf /var/lib/apt/lists/*
# Install dotnet tools
dotnet tool install fable -g
cd /build
dotnet run bundle
Bootstrap: docker
From: mcr.microsoft.com/dotnet/runtime:6.0
Stage: runtime
%files from build
/build/dist /app
%post
apt update \
&& apt install -y libnetcdf-dev
# Clean up
apt autoremove -y \
&& apt clean -y \
&& rm -rf /var/lib/apt/lists/*
%runscript
exec /app/FvcomStats "$@"

View File

@@ -1,22 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Include="Variables.fs" />
<Compile Include="NetCDF.fs" />
<Compile Include="Stats.fs" />
<Compile Include="Timeseries.fs" />
<Compile Include="Program.fs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="FSharp.Stats" Version="0.4.7" />
<PackageReference Include="Oceanbox.FvcomKit" Version="3.10.2" />
<PackageReference Include="sdslite" Version="2.5.0" />
</ItemGroup>
</Project>

22
helm/.helmignore Normal file
View File

@@ -0,0 +1,22 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*~
# Various IDEs
.project
.idea/
*.tmproj
.vscode/

21
helm/Chart.yaml Normal file
View File

@@ -0,0 +1,21 @@
apiVersion: v2
name: fvcom-stats
description: A Helm chart for Kubernetes
# A chart can be either an 'application' or a 'library' chart.
#
# Application charts are a collection of templates that can be packaged into versioned archives
# to be deployed.
#
# Library charts provide useful utilities or functions for the chart developer. They're included as
# a dependency of application charts to inject those utilities and functions into the rendering
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
type: application
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
version: 0.2.0
# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application.
appVersion: 1.10.0

View File

@@ -0,0 +1,4 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- base.yaml

View File

@@ -0,0 +1,3 @@
{
"ConnString" : "Data Source=/data/data.db"
}

View File

@@ -0,0 +1,25 @@
- op: test
path: /spec/rules/0/http/paths/0/path
value: /
# - op: replace
# path: /spec/rules/0/http/paths/0/path
# value:
# path: /app
# - op: add
# path: /spec/rules/-
# value:
# host: FvcomStats.oceanbox.io
# http:
# paths:
# - path: /
# pathType: Prefix
# backend:
# service:
# name: <deploy_name>
# port:
# number: 80
# - op: add
# path: /spec/tls/0/hosts/-
# value: FvcomStats.oceanbox.io

View File

@@ -0,0 +1,16 @@
namespace: <deploy_namespace>
secretGenerator:
- name: <deploy_name>
files:
- appsettings.json
generatorOptions:
disableNameSuffixHash: true
patchesJson6902:
- target:
group: networking.k8s.io
version: v1
kind: Ingress
name: <deploy_name>
path: ingress_patch.yaml
bases:
- ../base

View File

@@ -0,0 +1,5 @@
ingress:
annotations:
cert-manager.io/cluster-issuer: letsencrypt-production
nginx.ingress.kubernetes.io/whitelist-source-range: 0.0.0.0/0

View File

@@ -0,0 +1,3 @@
{
"ConnString" : "Data Source=/data/data.db"
}

View File

@@ -0,0 +1,25 @@
- op: test
path: /spec/rules/0/http/paths/0/path
value: /
# - op: replace
# path: /spec/rules/0/http/paths/0/path
# value:
# path: /app
# - op: add
# path: /spec/rules/-
# value:
# host: FvcomStats.dev.oceanbox.io
# http:
# paths:
# - path: /
# pathType: Prefix
# backend:
# service:
# name: <deploy_name>
# port:
# number: 80
# - op: add
# path: /spec/tls/0/hosts/-
# value: FvcomStats.dev.oceanbox.io

View File

@@ -0,0 +1,16 @@
namespace: <deploy_namespace>
secretGenerator:
- name: <deploy_name>
files:
- appsettings.json
generatorOptions:
disableNameSuffixHash: true
patchesJson6902:
- target:
group: networking.k8s.io
version: v1
kind: Ingress
name: <deploy_name>
path: ingress_patch.yaml
bases:
- ../base

View File

@@ -0,0 +1,4 @@
ingress:
annotations:
cert-manager.io/cluster-issuer: letsencrypt-production
nginx.ingress.kubernetes.io/whitelist-source-range: 10.0.0.0/8,172.16.0.0/12,192.168.0.0/16

21
helm/templates/NOTES.txt Normal file
View File

@@ -0,0 +1,21 @@
1. Get the application URL by running these commands:
{{- if .Values.ingress.enabled }}
{{- range $host := .Values.ingress.hosts }}
{{- range .paths }}
http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ . }}
{{- end }}
{{- end }}
{{- else if contains "NodePort" .Values.service.type }}
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "FvcomStats.fullname" . }})
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
echo http://$NODE_IP:$NODE_PORT
{{- else if contains "LoadBalancer" .Values.service.type }}
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "FvcomStats.fullname" . }}'
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "FvcomStats.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
echo http://$SERVICE_IP:{{ .Values.service.port }}
{{- else if contains "ClusterIP" .Values.service.type }}
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "FvcomStats.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
echo "Visit http://127.0.0.1:8080 to use your application"
kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:80
{{- end }}

View File

@@ -0,0 +1,65 @@
{{/* vim: set filetype=mustache: */}}
{{/*
Expand the name of the chart.
*/}}
{{- define "FvcomStats.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "FvcomStats.fullname" -}}
{{- if .Values.fullnameOverride -}}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- $name := default .Chart.Name .Values.nameOverride -}}
{{- if contains $name .Release.Name -}}
{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "FvcomStats.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/*
Common labels
*/}}
{{- define "FvcomStats.labels" -}}
helm.sh/chart: {{ include "FvcomStats.chart" . }}
{{ include "FvcomStats.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end -}}
{{/*
Selector labels
*/}}
{{- define "FvcomStats.selectorLabels" -}}
app: {{ include "FvcomStats.name" . }}
instance: {{ .Release.Name }}
app.kubernetes.io/name: {{ include "FvcomStats.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end -}}
{{/*
Create the name of the service account to use
*/}}
{{- define "FvcomStats.serviceAccountName" -}}
{{- if .Values.serviceAccount.create -}}
{{ default (include "FvcomStats.fullname" .) .Values.serviceAccount.name }}
{{- else -}}
{{ default "default" .Values.serviceAccount.name }}
{{- end -}}
{{- end -}}

View File

@@ -0,0 +1,119 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "FvcomStats.fullname" . }}
annotations:
{{- if .Values.ci.environment }}
app.gitlab.com/env: {{ default "" .Values.ci.environment }}
app.gitlab.com/app: {{ default "" .Values.ci.projectPath }}
{{- end }}
labels:
{{- include "FvcomStats.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
{{- include "FvcomStats.selectorLabels" . | nindent 6 }}
template:
metadata:
annotations:
{{- if .Values.ci.environment }}
app.gitlab.com/env: {{ default "" .Values.ci.environment }}
app.gitlab.com/app: {{ default "" .Values.ci.projectPath }}
{{- end }}
labels:
{{- include "FvcomStats.selectorLabels" . | nindent 8 }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
serviceAccountName: {{ include "FvcomStats.serviceAccountName" . }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
containers:
- name: {{ .Chart.Name }}
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: 8085
protocol: TCP
livenessProbe:
httpGet:
path: /
port: http
{{- if .Values.service.https }}
scheme: HTTPS
{{- end }}
readinessProbe:
httpGet:
path: /
port: http
{{- if .Values.service.https }}
scheme: HTTPS
{{- end }}
{{- if .Values.service.https }}
env:
- name: ASPNETCORE_Kestrel__Certificates__Default__Path
value: "/app/tls/kestrel.pfx"
- name: SERVER_USE_HTTPS
value: "1"
{{- else }}
env: []
{{- end }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
volumeMounts:
- name: data
mountPath: /data
- name: appsettings
mountPath: /app/appsettings.json
subPath: appsettings.json
readOnly: true
{{- if .Values.service.https }}
- name: tls-certificates
mountPath: /app/tls
readOnly: true
{{- end }}
initContainers:
- name: init
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
command: [ "/bin/sh", "-c", "true"]
volumeMounts:
- name: data
mountPath: /data
- name: appsettings
mountPath: /app/appsettings.json
subPath: appsettings.json
readOnly: true
volumes:
- name: data
{{- if .Values.persistence.enabled }}
persistentVolumeClaim:
claimName: {{ .Values.persistence.existingClaim | default (include "FvcomStats.fullname" .) }}
{{- else }}
emptyDir: {}
{{- end }}
- name: appsettings
secret:
secretName: {{ template "FvcomStats.fullname" . }}
{{- if .Values.service.https }}
- name: tls-certificates
secret:
secretName: {{ .Values.service.secretName }}
{{- end }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}

View File

@@ -0,0 +1,64 @@
{{- if .Values.ingress.enabled -}}
{{- $fullName := include "FvcomStats.fullname" . -}}
{{- $svcPort := .Values.service.port -}}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ $fullName }}
labels:
{{- include "FvcomStats.labels" . | nindent 4 }}
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/ssl-redirect: "true"
{{- if .Values.service.https }}
nginx.ingress.kubernetes.io/backend-protocol: HTTPS
{{- else }}
nginx.ingress.kubernetes.io/backend-protocol: HTTP
{{- end }}
{{- with .Values.ingress.annotations }}
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
tls:
{{- if .Values.ci.deployHost }}
- hosts:
- {{ .Values.ci.deployHost }}
secretName: {{ .Release.Name }}-tls
{{- end }}
{{- if .Values.ingress.tls }}
{{- range .Values.ingress.tls }}
- hosts:
{{- range .hosts }}
- {{ . | quote }}
{{- end }}
secretName: {{ .secretName }}
{{- end }}
{{- end }}
rules:
{{- if .Values.ci.deployHost }}
- host: {{ .Values.ci.deployHost }}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: {{ $fullName }}
port:
number: {{ $svcPort }}
{{- end }}
{{- range .Values.ingress.hosts }}
- host: {{ .host | quote }}
http:
paths:
{{- range .paths }}
- path: {{ . }}
pathType: Prefix
backend:
service:
name: {{ $fullName }}
port:
number: {{ $svcPort }}
{{- end }}
{{- end }}
{{- end }}

25
helm/templates/pvc.yaml Normal file
View File

@@ -0,0 +1,25 @@
{{- if and .Values.persistence.enabled (not .Values.persistence.existingClaim) }}
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: {{ template "FvcomStats.fullname" . }}
{{- with .Values.persistence.annotations }}
annotations:
{{ toYaml . | indent 4 }}
{{- end }}
labels:
{{ include "FvcomStats.labels" . | indent 4 }}
spec:
accessModes:
- {{ .Values.persistence.accessMode | quote }}
resources:
requests:
storage: {{ .Values.persistence.size | quote }}
{{- if .Values.persistence.storageClass }}
{{- if (eq "-" .Values.persistence.storageClass) }}
storageClassName: ""
{{- else }}
storageClassName: "{{ .Values.persistence.storageClass }}"
{{- end }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,15 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "FvcomStats.fullname" . }}
labels:
{{- include "FvcomStats.labels" . | nindent 4 }}
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: http
protocol: TCP
name: http
selector:
{{- include "FvcomStats.selectorLabels" . | nindent 4 }}

View File

@@ -0,0 +1,8 @@
{{- if .Values.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "FvcomStats.serviceAccountName" . }}
labels:
{{ include "FvcomStats.labels" . | nindent 4 }}
{{- end -}}

73
helm/values.yaml Normal file
View File

@@ -0,0 +1,73 @@
# Default values for FvcomStats.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
replicaCount: 1
image:
repository: overwritten by CD
tag: latest
pullPolicy: IfNotPresent
imagePullSecrets:
- name: gitlab-pull-secret
nameOverride: ""
fullnameOverride: ""
serviceAccount:
# Specifies whether a service account should be created
create: true
# The name of the service account to use.
# If not set and create is true, a name is generated using the fullname template
name:
podSecurityContext:
fsGroup: 2000
securityContext:
capabilities:
drop:
- ALL
readOnlyRootFilesystem: false
runAsNonRoot: true
runAsUser: 1000
service:
type: ClusterIP
port: 80
https: false
secretName: kestrel-tls
ingress:
enabled: true
persistence:
enabled: false
size: 1G
storageClass: ""
accessMode: ReadWriteOnce
ci:
environment: ""
projectPath: ""
deployHost: ""
resources: {}
# We usually recommend not to specify default resources and to leave this as a conscious
# choice for the user. This also increases chances charts run on environments with little
# resources, such as Minikube. If you do want to specify resources, uncomment the following
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
# limits:
# cpu: 100m
# memory: 128Mi
# requests:
# cpu: 100m
# memory: 128Mi
nodeSelector: {}
tolerations: []
affinity: {}

12505
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

11
package.json Normal file
View File

@@ -0,0 +1,11 @@
{
"private": true,
"devDependencies": {
"@semantic-release/changelog": "^6.0.1",
"@semantic-release/exec": "^6.0.3",
"@semantic-release/git": "^10.0.1",
"@semantic-release/gitlab": "^7.0.4",
"semantic-release-dotnet": "^1.0.0"
},
"dependencies": {}
}

27
src/FvcomStats.fsproj Normal file
View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Include="Variables.fs" />
<Compile Include="NetCDF.fs" />
<Compile Include="Stats.fs" />
<Compile Include="Timeseries.fs" />
<Compile Include="Program.fs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Argu" Version="6.1.1" />
<PackageReference Include="FSharp.Data" Version="6.0.1-beta001" />
<PackageReference Include="FSharp.Stats" Version="0.4.8" />
<PackageReference Include="FSharpPlus" Version="1.3.0-CI02744" />
<PackageReference Include="Serilog" Version="2.12.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.1-dev-00896" />
<PackageReference Include="Serilog.Sinks.Seq" Version="5.2.1" />
<PackageReference Include="Thoth.Json.Net" Version="8.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\submodules\Oceanbox.FvcomKit\src\Oceanbox.FvcomKit.fsproj" />
</ItemGroup>
</Project>

47
src/Main.fs Normal file
View File

@@ -0,0 +1,47 @@
module Main
open System
open Serilog
open Serilog.Events
open Argu
open Settings
let configureSerilog level =
let n =
match level with
| 0 -> LogEventLevel.Error
| 1 -> LogEventLevel.Warning
| 2 -> LogEventLevel.Information
| 3 -> LogEventLevel.Debug
| _ -> LogEventLevel.Verbose
LoggerConfiguration()
.MinimumLevel.Is(n)
.WriteTo.Console()
.CreateLogger()
type Arguments =
| Log_Level of level: int
| [<MainCommand; ExactlyOnce; Last>] File of file: string
interface IArgParserTemplate with
member this.Usage =
match this with
| Log_Level _ -> "0=Error, 1=Warning, 2=Info, 3=Debug, 4=Verbose"
| File _ -> "file"
let colorizer =
function
| ErrorCode.HelpText -> None
| _ -> Some ConsoleColor.Red
let errorHandler = ProcessExiter(colorizer = colorizer)
[<EntryPoint>]
let main argv =
let parser =
ArgumentParser.Create<Arguments>(programName = "FvcomStats", errorHandler = errorHandler)
let args = parser.Parse argv
Log.Logger <- configureSerilog (args.GetResult(Log_Level, defaultValue = 2))
Log.Information $"File is {args.GetResult File}"
0

23
src/Settings.fs Normal file
View File

@@ -0,0 +1,23 @@
module Settings
open System.IO
open Thoth.Json.Net
open Serilog
type Settings = { Setting: string }
let tryGetEnv =
System.Environment.GetEnvironmentVariable
>> function
| null
| "" -> None
| x -> Some x
let appsettings =
let settings = System.IO.File.ReadAllText "appsettings.json"
match Decode.Auto.fromString<Settings> settings with
| Ok s -> s
| Error e -> failwith e
sprintf "AppSettings: %A" appsettings |> Log.Debug

View File

@@ -1,21 +1,23 @@
module Stats
open FSharp.Stats.Quantile
open FSharp.Stats.SummaryStats
open FSharp.Stats
type Stats =
{
VarName: string
VarName: string
Ind: int
IndZ: int
Mean: float32
Std: float32
Var: float32
Q05: float32
Q25: float32
Q50: float32
Q75: float32
Q95: float32
Q99: float32
Q05: float32
Q25: float32
Q50: float32
Q75: float32
Q95: float32
Q99: float32
}
type StatsMonthly =
{
@@ -26,36 +28,36 @@ type Stats =
Mean: float32
Std: float32
Var: float32
Q05: float32
Q25: float32
Q50: float32
Q75: float32
Q95: float32
Q99: float32
}
Q05: float32
Q25: float32
Q50: float32
Q75: float32
Q95: float32
Q99: float32
}
let computeQuantiles (data: float []) (quantiles: float []) =
let q =
quantiles
|> Array.map (fun qi -> california qi data)
q[0], q[1], q[2], q[3], q[4], q[5]
let uv2dr (u: float32 []) (v: float32 []) =
0
let computeStats (varName: string) (ind: int) (indZ: int) (data: float[]) =
let mean = Seq.average data
let std = Seq.stDevPopulation data
let variance =Seq.varPopulation data
let variance =Seq.varPopulation data
let q05, q25, q50, q75, q95, q99 = computeQuantiles data [|0.05; 0.25; 0.5; 0.75; 0.95; 0.99|]
{
VarName = varName
VarName = varName
Ind = ind
IndZ = indZ
IndZ = indZ
Mean = float32 mean
Std = float32 std
Var = float32 variance
@@ -71,13 +73,13 @@ let computeStats (varName: string) (ind: int) (indZ: int) (data: float[]) =
let computeMonthlyStats (varName: string) (month: int) (ind: int) (indZ: int) (data: float[]) =
let mean = Seq.average data
let std = Seq.stDevPopulation data
let variance =Seq.varPopulation data
let variance =Seq.varPopulation data
let q05, q25, q50, q75, q95, q99 = computeQuantiles data [|0.05; 0.25; 0.5; 0.75; 0.95; 0.99|]
{
VarName = varName
month = month
Ind = ind
IndZ = indZ
IndZ = indZ
Mean = float32 mean
Std = float32 std
Var = float32 variance
@@ -88,35 +90,35 @@ let computeMonthlyStats (varName: string) (month: int) (ind: int) (indZ: int) (d
Q95 = float32 q95
Q99 = float32 q99
}
let analyseScalarTimeSeries (varName: string) (data: float32 [,,]) (startInd: int) (nNodes: int) =
let nSiglays = (Array3D.length2 data) - 1
let m =
[| for z in 0..nSiglays do
for n in startInd..(startInd+nNodes-1) do
for n in startInd..(startInd+nNodes-1) do
n, z, data[*, z, n-startInd]
|> Array.map float
|> Array.map float
|]
let stats =
m
|> Array.Parallel.map (fun (ind, indZ, a) -> computeStats varName ind indZ a)
stats
stats
let analyseScalarTimeSeriesMonthly (varName: string) (month:int) (data: float32 [,,]) (startInd: int) (nNodes: int) =
let nSiglays = (Array3D.length2 data) - 1
let m =
[| for z in 0..nSiglays do
for n in startInd..(startInd+nNodes-1) do
for n in startInd..(startInd+nNodes-1) do
n, z, data[*, z, n-startInd]
|> Array.map float
|> Array.map float
|]
let stats =
m
|> Array.Parallel.map (fun (ind, indZ, a) -> computeMonthlyStats varName month ind indZ a)
stats
stats

3
src/appsettings.json Normal file
View File

@@ -0,0 +1,3 @@
{
"Setting" : "example setting"
}

18
test/Tests.fs Normal file
View File

@@ -0,0 +1,18 @@
module Tests
open Expecto
let server =
testList
"Server"
[
testCase "Adding valid Todo"
<| fun _ ->
let expectedResult = Ok()
Expect.equal (Ok()) expectedResult "Result should be ok"
]
let all = testList "All" [ server ]
[<EntryPoint>]
let main _ = runTests defaultConfig all

16
test/Tests.fsproj Normal file
View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Include="Tests.fs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\src\FvcomStats.fsproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Expecto" Version="9.0.4" />
</ItemGroup>
</Project>