Initial commit

This commit is contained in:
Mustafa Gezen 2022-07-07 22:11:50 +02:00
commit ce632b9498
Signed by untrusted user who does not match committer: mustafa
GPG Key ID: DCDF010D946438C1
6786 changed files with 1960134 additions and 0 deletions

5
.bazelignore Normal file
View File

@ -0,0 +1,5 @@
pkg/dep
**/*.bazel_ignore
node_modules
ci_output
vendor/github.com/grpc-ecosystem/grpc-gateway

23
.bazelrc Normal file
View File

@ -0,0 +1,23 @@
# Stamp script
build --workspace_status_command=tools/status.sh
run --workspace_status_command=tools/status.sh
# Just build tests when testing
test --build_tests_only
build --incompatible_strict_action_env=true
# Minimize what is downloaded
build:inmemory --experimental_inmemory_jdeps_files
build:inmemory --experimental_inmemory_dotd_files
# Minimize what is downloaded
build:toplevel --config=inmemory
build:toplevel --experimental_remote_download_outputs=toplevel
build:remote --config=toplevel
build:remote --google_credentials=/tmp/credentials.json
build:remote --remote_cache=https://storage.googleapis.com/resf-temporary-bazel-cache
run:remote --experimental_remote_download_outputs=all --noexperimental_inmemory_jdeps_files --noexperimental_inmemory_dotd_files
build --stamp=true

1
.bazelversion Normal file
View File

@ -0,0 +1 @@
5.0.0

19
.editorconfig Normal file
View File

@ -0,0 +1,19 @@
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true
end_of_line = lf
[*.md]
max_line_length = off
trim_trailing_whitespace = false
[*.go]
indent_size = 4
[*.py]
indent_size = 4

11
.envrc Normal file
View File

@ -0,0 +1,11 @@
# direnv
unset STABLE_LOCAL_ENVIRONMENT STABLE_OCI_REGISTRY STABLE_OCI_REGISTRY_REPO
export STABLE_STAGE="-dev"
export STABLE_LOCAL_ENVIRONMENT=1
export STABLE_OCI_REGISTRY="host.docker.internal.local:5000"
export STABLE_OCI_REGISTRY_REPO="dev"
export IBAZEL_USE_LEGACY_WATCHER=0
export STABLE_REGISTRY_SECRET="none"
export STABLE_OCI_REGISTRY_NO_NESTED_SUPPORT_IN_2022_SHAME_ON_YOU_AWS="true"
PATH_add hack

8
.envrc.prod.extarches Normal file
View File

@ -0,0 +1,8 @@
unset STABLE_LOCAL_ENVIRONMENT STABLE_OCI_REGISTRY STABLE_OCI_REGISTRY_REPO STABLE_OCI_REGISTRY_NO_NESTED_SUPPORT_IN_2022_SHAME_ON_YOU_AWS
export STABLE_STAGE="-prod"
export STABLE_REGISTRY_SECRET="none"
export STABLE_OCI_REGISTRY="quay.io"
export STABLE_OCI_REGISTRY_REPO="peridot/monoregistry"
export STABLE_SITE="extarches"
export STABLE_OCI_REGISTRY_NO_NESTED_SUPPORT_IN_2022_SHAME_ON_YOU_AWS="true"

6
.envrc.prod.quaymirror Normal file
View File

@ -0,0 +1,6 @@
unset STABLE_LOCAL_ENVIRONMENT STABLE_OCI_REGISTRY STABLE_OCI_REGISTRY_REPO STABLE_OCI_REGISTRY_NO_NESTED_SUPPORT_IN_2022_SHAME_ON_YOU_AWS STABLE_SITE
export STABLE_STAGE="-prod"
export STABLE_REGISTRY_SECRET="none"
export STABLE_OCI_REGISTRY="quay.io"
export STABLE_OCI_REGISTRY_REPO="peridot"

39
.envrc.prod.resf Normal file
View File

@ -0,0 +1,39 @@
#
# Copyright (c) All respective contributors to the Peridot Project. All rights reserved.
# Copyright (c) 2021-2022 Rocky Enterprise Software Foundation, Inc. All rights reserved.
# Copyright (c) 2021-2022 Ctrl IQ, Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names of its contributors
# may be used to endorse or promote products derived from this software without
# specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
unset STABLE_LOCAL_ENVIRONMENT STABLE_OCI_REGISTRY STABLE_OCI_REGISTRY_REPO
export STABLE_STAGE="-prod"
export STABLE_REGISTRY_SECRET="none"
export STABLE_OCI_REGISTRY="893168113496.dkr.ecr.us-east-2.amazonaws.com"
export STABLE_OCI_REGISTRY_REPO="resf-internal-registry"
export STABLE_OCI_REGISTRY_NO_NESTED_SUPPORT_IN_2022_SHAME_ON_YOU_AWS="true"

116
.gitignore vendored Normal file
View File

@ -0,0 +1,116 @@
# Ignore all bazel-* symlinks. There is no full list since this can change
# based on the name of the directory bazel is cloned into.
/bazel-*
### Java template
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
node_modules
yarn-error.log
.local
vendor/peridot.resf.org
*_secret_mock.sql
*.iml
# User-specific stuff
.ijwb/.idea/**/workspace.xml
.ijwb/.idea/**/tasks.xml
.ijwb/.idea/**/usage.statistics.xml
.ijwb/.idea/**/dictionaries
.ijwb/.idea/**/shelf
# AWS User-specific
.ijwb/.idea/**/aws.xml
# Generated files
.ijwb/.idea/**/contentModel.xml
# Sensitive or high-churn files
.ijwb/.idea/**/dataSources/
.ijwb/.idea/**/dataSources.ids
.ijwb/.idea/**/dataSources.local.xml
.ijwb/.idea/**/sqlDataSources.xml
.ijwb/.idea/**/dynamic.xml
.ijwb/.idea/**/uiDesigner.xml
.ijwb/.idea/**/dbnavigator.xml
# Gradle
.ijwb/.idea/**/gradle.xml
.ijwb/.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.ijwb/.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.ijwb/.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.ijwb/.idea/replstate.xml
# SonarLint plugin
.ijwb/.idea/sonarlint/
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.ijwb/.idea/httpRequests
# Android studio 3.1+ serialized cache file
.ijwb/.idea/caches/build_file_checksums.ser
.ijwb/.idea/runConfigurations.xml
.ijwb/.idea/google-java-format.xml
.ijwb/.idea/dataSources.xml

39
.gitlab-ci.yml Normal file
View File

@ -0,0 +1,39 @@
#!/usr/bin/env bash
stages:
- bazel
variables:
SILO_KEY: rocky84-gitlabcom-ci-1
REMOTE_DEF: cache-silo-key=$SILO_KEY
REPO_OUTPUT_DIR: ci_repo_output
.bazelbase:
image: quay.io/peridot/ci:v0.2.5
before_script:
- mv $google_credentials /tmp/credentials.json
cache:
key: $SILO_KEY
paths:
- $REPO_OUTPUT_DIR
bazel-build:
extends: .bazelbase
stage: bazel
script:
- bash hack/run_ci build
bazel-lint:
extends: .bazelbase
stage: bazel
script:
- bash hack/run_ci lint
bazel-test:
extends: .bazelbase
stage: bazel
script:
- bash hack/run_ci test
artifacts:
when: always
reports:
junit: bazel-out/*-fastbuild/testlogs/**/*.xml

9
.ijwb/.bazelproject Normal file
View File

@ -0,0 +1,9 @@
directories:
.
derive_targets_from_directories: true
additional_languages:
go
javascript
typescript

1
.ijwb/.idea/.name Normal file
View File

@ -0,0 +1 @@
peridot

View File

@ -0,0 +1,603 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<option name="OTHER_INDENT_OPTIONS">
<value>
<option name="INDENT_SIZE" value="2" />
<option name="CONTINUATION_INDENT_SIZE" value="4" />
<option name="TAB_SIZE" value="2" />
</value>
</option>
<option name="RIGHT_MARGIN" value="100" />
<option name="KEEP_CONTROL_STATEMENT_IN_ONE_LINE" value="false" />
<option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="0" />
<option name="ALIGN_MULTILINE_PARAMETERS" value="false" />
<option name="ALIGN_MULTILINE_FOR" value="false" />
<option name="SPACE_BEFORE_ARRAY_INITIALIZER_LBRACE" value="true" />
<option name="CALL_PARAMETERS_WRAP" value="1" />
<option name="METHOD_PARAMETERS_WRAP" value="1" />
<option name="EXTENDS_LIST_WRAP" value="1" />
<option name="THROWS_KEYWORD_WRAP" value="1" />
<option name="METHOD_CALL_CHAIN_WRAP" value="1" />
<option name="BINARY_OPERATION_WRAP" value="1" />
<option name="BINARY_OPERATION_SIGN_ON_NEXT_LINE" value="true" />
<option name="TERNARY_OPERATION_WRAP" value="1" />
<option name="TERNARY_OPERATION_SIGNS_ON_NEXT_LINE" value="true" />
<option name="FOR_STATEMENT_WRAP" value="1" />
<option name="ARRAY_INITIALIZER_WRAP" value="1" />
<option name="WRAP_COMMENTS" value="true" />
<option name="IF_BRACE_FORCE" value="3" />
<option name="DOWHILE_BRACE_FORCE" value="3" />
<option name="WHILE_BRACE_FORCE" value="3" />
<option name="FOR_BRACE_FORCE" value="3" />
<AndroidXmlCodeStyleSettings>
<option name="USE_CUSTOM_SETTINGS" value="true" />
<option name="LAYOUT_SETTINGS">
<value>
<option name="INSERT_BLANK_LINE_BEFORE_TAG" value="false" />
</value>
</option>
</AndroidXmlCodeStyleSettings>
<HTMLCodeStyleSettings>
<option name="HTML_SPACE_INSIDE_EMPTY_TAG" value="true" />
<option name="HTML_QUOTE_STYLE" value="Single" />
<option name="HTML_ENFORCE_QUOTES" value="true" />
</HTMLCodeStyleSettings>
<JSCodeStyleSettings version="0">
<option name="FORCE_SEMICOLON_STYLE" value="true" />
<option name="SPACE_BEFORE_FUNCTION_LEFT_PARENTH" value="false" />
<option name="USE_DOUBLE_QUOTES" value="false" />
<option name="FORCE_QUOTE_STYlE" value="true" />
<option name="ENFORCE_TRAILING_COMMA" value="Remove" />
<option name="SPACES_WITHIN_OBJECT_LITERAL_BRACES" value="true" />
<option name="SPACES_WITHIN_IMPORTS" value="true" />
<option name="INDENT_CHAINED_CALLS" value="false" />
</JSCodeStyleSettings>
<JavaCodeStyleSettings>
<option name="INSERT_INNER_CLASS_IMPORTS" value="true" />
<option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="999" />
<option name="NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND" value="999" />
<option name="PACKAGES_TO_USE_IMPORT_ON_DEMAND">
<value />
</option>
<option name="IMPORT_LAYOUT_TABLE">
<value>
<package name="" withSubpackages="true" static="true" />
<emptyLine />
<package name="" withSubpackages="true" static="false" />
</value>
</option>
</JavaCodeStyleSettings>
<Objective-C>
<option name="INDENT_NAMESPACE_MEMBERS" value="0" />
<option name="INDENT_C_STRUCT_MEMBERS" value="2" />
<option name="INDENT_CLASS_MEMBERS" value="2" />
<option name="INDENT_VISIBILITY_KEYWORDS" value="1" />
<option name="INDENT_INSIDE_CODE_BLOCK" value="2" />
<option name="KEEP_STRUCTURES_IN_ONE_LINE" value="true" />
<option name="FUNCTION_PARAMETERS_WRAP" value="5" />
<option name="FUNCTION_CALL_ARGUMENTS_WRAP" value="5" />
<option name="TEMPLATE_CALL_ARGUMENTS_WRAP" value="5" />
<option name="TEMPLATE_CALL_ARGUMENTS_ALIGN_MULTILINE" value="true" />
<option name="ALIGN_INIT_LIST_IN_COLUMNS" value="false" />
<option name="SPACE_BEFORE_SUPERCLASS_COLON" value="false" />
</Objective-C>
<Objective-C-extensions>
<option name="GENERATE_INSTANCE_VARIABLES_FOR_PROPERTIES" value="ASK" />
<option name="RELEASE_STYLE" value="IVAR" />
<option name="TYPE_QUALIFIERS_PLACEMENT" value="BEFORE" />
<file>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Macro" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Typedef" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Enum" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Constant" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Global" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Struct" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="FunctionPredecl" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Function" />
</file>
<class>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Property" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Synthesize" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InitMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="StaticMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InstanceMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="DeallocMethod" />
</class>
<extensions>
<pair source="cc" header="h" />
<pair source="c" header="h" />
</extensions>
</Objective-C-extensions>
<TypeScriptCodeStyleSettings version="0">
<option name="FORCE_SEMICOLON_STYLE" value="true" />
<option name="SPACE_BEFORE_FUNCTION_LEFT_PARENTH" value="false" />
<option name="USE_DOUBLE_QUOTES" value="false" />
<option name="FORCE_QUOTE_STYlE" value="true" />
<option name="ENFORCE_TRAILING_COMMA" value="Remove" />
<option name="SPACES_WITHIN_OBJECT_LITERAL_BRACES" value="true" />
<option name="SPACES_WITHIN_IMPORTS" value="true" />
<option name="INDENT_CHAINED_CALLS" value="false" />
<option name="IMPORT_PREFER_ABSOLUTE_PATH" value="TRUE" />
</TypeScriptCodeStyleSettings>
<XML>
<option name="XML_ALIGN_ATTRIBUTES" value="false" />
</XML>
<codeStyleSettings language="CSS">
<indentOptions>
<option name="INDENT_SIZE" value="2" />
<option name="CONTINUATION_INDENT_SIZE" value="4" />
<option name="TAB_SIZE" value="2" />
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="ECMA Script Level 4">
<option name="KEEP_BLANK_LINES_IN_CODE" value="1" />
<option name="ALIGN_MULTILINE_PARAMETERS" value="false" />
<option name="ALIGN_MULTILINE_FOR" value="false" />
<option name="CALL_PARAMETERS_WRAP" value="1" />
<option name="METHOD_PARAMETERS_WRAP" value="1" />
<option name="EXTENDS_LIST_WRAP" value="1" />
<option name="BINARY_OPERATION_WRAP" value="1" />
<option name="BINARY_OPERATION_SIGN_ON_NEXT_LINE" value="true" />
<option name="TERNARY_OPERATION_WRAP" value="1" />
<option name="TERNARY_OPERATION_SIGNS_ON_NEXT_LINE" value="true" />
<option name="FOR_STATEMENT_WRAP" value="1" />
<option name="ARRAY_INITIALIZER_WRAP" value="1" />
<option name="IF_BRACE_FORCE" value="3" />
<option name="DOWHILE_BRACE_FORCE" value="3" />
<option name="WHILE_BRACE_FORCE" value="3" />
<option name="FOR_BRACE_FORCE" value="3" />
<option name="PARENT_SETTINGS_INSTALLED" value="true" />
</codeStyleSettings>
<codeStyleSettings language="HTML">
<option name="SOFT_MARGINS" value="80" />
<indentOptions>
<option name="INDENT_SIZE" value="2" />
<option name="CONTINUATION_INDENT_SIZE" value="2" />
<option name="TAB_SIZE" value="2" />
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="JAVA">
<option name="KEEP_CONTROL_STATEMENT_IN_ONE_LINE" value="false" />
<option name="KEEP_BLANK_LINES_IN_CODE" value="1" />
<option name="BLANK_LINES_AFTER_CLASS_HEADER" value="1" />
<option name="ALIGN_MULTILINE_PARAMETERS" value="false" />
<option name="ALIGN_MULTILINE_RESOURCES" value="false" />
<option name="ALIGN_MULTILINE_FOR" value="false" />
<option name="CALL_PARAMETERS_WRAP" value="1" />
<option name="METHOD_PARAMETERS_WRAP" value="1" />
<option name="EXTENDS_LIST_WRAP" value="1" />
<option name="THROWS_KEYWORD_WRAP" value="1" />
<option name="METHOD_CALL_CHAIN_WRAP" value="1" />
<option name="BINARY_OPERATION_WRAP" value="1" />
<option name="BINARY_OPERATION_SIGN_ON_NEXT_LINE" value="true" />
<option name="TERNARY_OPERATION_WRAP" value="1" />
<option name="TERNARY_OPERATION_SIGNS_ON_NEXT_LINE" value="true" />
<option name="FOR_STATEMENT_WRAP" value="1" />
<option name="ARRAY_INITIALIZER_WRAP" value="1" />
<option name="WRAP_COMMENTS" value="true" />
<option name="IF_BRACE_FORCE" value="3" />
<option name="DOWHILE_BRACE_FORCE" value="3" />
<option name="WHILE_BRACE_FORCE" value="3" />
<option name="FOR_BRACE_FORCE" value="3" />
<indentOptions>
<option name="INDENT_SIZE" value="2" />
<option name="CONTINUATION_INDENT_SIZE" value="4" />
<option name="TAB_SIZE" value="2" />
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="JSON">
<indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="4" />
<option name="TAB_SIZE" value="2" />
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="JavaScript">
<option name="RIGHT_MARGIN" value="80" />
<option name="KEEP_BLANK_LINES_IN_CODE" value="1" />
<option name="ALIGN_MULTILINE_PARAMETERS" value="false" />
<option name="ALIGN_MULTILINE_FOR" value="false" />
<option name="CALL_PARAMETERS_WRAP" value="1" />
<option name="METHOD_PARAMETERS_WRAP" value="1" />
<option name="BINARY_OPERATION_WRAP" value="1" />
<option name="BINARY_OPERATION_SIGN_ON_NEXT_LINE" value="true" />
<option name="TERNARY_OPERATION_WRAP" value="1" />
<option name="TERNARY_OPERATION_SIGNS_ON_NEXT_LINE" value="true" />
<option name="FOR_STATEMENT_WRAP" value="1" />
<option name="ARRAY_INITIALIZER_WRAP" value="1" />
<option name="IF_BRACE_FORCE" value="3" />
<option name="DOWHILE_BRACE_FORCE" value="3" />
<option name="WHILE_BRACE_FORCE" value="3" />
<option name="FOR_BRACE_FORCE" value="3" />
<option name="SOFT_MARGINS" value="80" />
<indentOptions>
<option name="INDENT_SIZE" value="2" />
<option name="CONTINUATION_INDENT_SIZE" value="2" />
<option name="TAB_SIZE" value="2" />
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="ObjectiveC">
<option name="RIGHT_MARGIN" value="80" />
<option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="1" />
<option name="BLANK_LINES_BEFORE_IMPORTS" value="0" />
<option name="BLANK_LINES_AFTER_IMPORTS" value="0" />
<option name="BLANK_LINES_AROUND_CLASS" value="0" />
<option name="BLANK_LINES_AROUND_METHOD" value="0" />
<option name="BLANK_LINES_AROUND_METHOD_IN_INTERFACE" value="0" />
<option name="ALIGN_MULTILINE_BINARY_OPERATION" value="false" />
<option name="BINARY_OPERATION_SIGN_ON_NEXT_LINE" value="true" />
<option name="FOR_STATEMENT_WRAP" value="1" />
<option name="ASSIGNMENT_WRAP" value="1" />
<indentOptions>
<option name="INDENT_SIZE" value="2" />
<option name="CONTINUATION_INDENT_SIZE" value="4" />
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="PROTO">
<option name="RIGHT_MARGIN" value="80" />
<indentOptions>
<option name="INDENT_SIZE" value="2" />
<option name="CONTINUATION_INDENT_SIZE" value="2" />
<option name="TAB_SIZE" value="2" />
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="Python">
<option name="RIGHT_MARGIN" value="80" />
<option name="ALIGN_MULTILINE_PARAMETERS" value="false" />
<indentOptions>
<option name="INDENT_SIZE" value="2" />
<option name="CONTINUATION_INDENT_SIZE" value="4" />
<option name="TAB_SIZE" value="2" />
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="SASS">
<indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="4" />
<option name="TAB_SIZE" value="2" />
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="SCSS">
<indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="4" />
<option name="TAB_SIZE" value="2" />
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="TypeScript">
<option name="SOFT_MARGINS" value="80" />
<indentOptions>
<option name="INDENT_SIZE" value="2" />
<option name="CONTINUATION_INDENT_SIZE" value="2" />
<option name="TAB_SIZE" value="2" />
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="XML">
<indentOptions>
<option name="INDENT_SIZE" value="2" />
<option name="CONTINUATION_INDENT_SIZE" value="2" />
<option name="TAB_SIZE" value="2" />
</indentOptions>
<arrangement>
<rules>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:android</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:id</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>style</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:.*Style</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:layout_width</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:layout_height</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:layout_weight</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:layout_margin</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:layout_marginTop</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:layout_marginBottom</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:layout_marginStart</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:layout_marginEnd</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:layout_marginLeft</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:layout_marginRight</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:layout_.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:padding</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:paddingTop</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:paddingBottom</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:paddingStart</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:paddingEnd</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:paddingLeft</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:paddingRight</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_NAMESPACE>http://schemas.android.com/apk/res-auto</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_NAMESPACE>http://schemas.android.com/tools</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_NAMESPACE>.*</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
</rules>
</arrangement>
</codeStyleSettings>
<codeStyleSettings language="protobuf">
<option name="RIGHT_MARGIN" value="80" />
<indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="2" />
</indentOptions>
</codeStyleSettings>
</code_scheme>
</component>

View File

@ -0,0 +1,5 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
</state>
</component>

View File

@ -0,0 +1,6 @@
<component name="CopyrightManager">
<copyright>
<option name="notice" value="Copyright (c) All respective contributors to the Peridot Project. All rights reserved.&#10;Copyright (c) 2021-2022 Rocky Enterprise Software Foundation, Inc. All rights reserved.&#10;Copyright (c) 2021-2022 Ctrl IQ, Inc. All rights reserved.&#10;&#10;Redistribution and use in source and binary forms, with or without&#10;modification, are permitted provided that the following conditions are met:&#10;&#10;1. Redistributions of source code must retain the above copyright notice,&#10;this list of conditions and the following disclaimer.&#10;&#10;2. Redistributions in binary form must reproduce the above copyright notice,&#10;this list of conditions and the following disclaimer in the documentation&#10;and/or other materials provided with the distribution.&#10;&#10;3. Neither the name of the copyright holder nor the names of its contributors&#10;may be used to endorse or promote products derived from this software without&#10;specific prior written permission.&#10;&#10;THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &quot;AS IS&quot;&#10;AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE&#10;IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE&#10;ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE&#10;LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR&#10;CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF&#10;SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS&#10;INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN&#10;CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)&#10;ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE&#10;POSSIBILITY OF SUCH DAMAGE." />
<option name="myName" value="Peridot" />
</copyright>
</component>

View File

@ -0,0 +1,11 @@
<component name="CopyrightManager">
<settings>
<module2copyright>
<element module="OriginalFiles" copyright="Peridot" />
</module2copyright>
<LanguageOptions name="Go">
<option name="fileTypeOverride" value="3" />
<option name="block" value="false" />
</LanguageOptions>
</settings>
</component>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptLibraryMappings">
<file url="file://$PROJECT_DIR$/.." libraries="{Node.js Core}" />
</component>
</project>

7
.ijwb/.idea/misc.xml Normal file
View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="FrameworkDetectionExcludesConfiguration">
<type id="android" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="11" project-jdk-type="JavaSDK" />
</project>

9
.ijwb/.idea/modules.xml Normal file
View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.blaze/modules/.project-data-dir.iml" filepath="$PROJECT_DIR$/.blaze/modules/.project-data-dir.iml" />
<module fileurl="file://$PROJECT_DIR$/.blaze/modules/.workspace.iml" filepath="$PROJECT_DIR$/.blaze/modules/.workspace.iml" />
</modules>
</component>
</project>

6
.ijwb/.idea/prettier.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="PrettierConfiguration">
<option name="myRunOnReformat" value="true" />
</component>
</project>

View File

@ -0,0 +1,3 @@
<component name="DependencyValidationManager">
<scope name="OriginalFiles" pattern="file[.workspace]:*/&amp;&amp;!file[.workspace]:build/bazel/remote/execution/v2//*&amp;&amp;!file[.workspace]:build/bazel/semver//*&amp;&amp;!file[.workspace]:build/bazel/protobuf//*&amp;&amp;!file[.workspace]:third_party//*&amp;&amp;!file[.workspace]:validate//*&amp;&amp;!file[.workspace]:protoc-gen-openapiv2//*&amp;&amp;!file[.workspace]:protoc-gen-openapiv2/options//*" />
</component>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="SqlDialectMappings">
<file url="file://$PROJECT_DIR$/../peridot/seed.sql" dialect="PostgreSQL" />
<file url="PROJECT" dialect="PostgreSQL" />
</component>
</project>

6
.ijwb/.idea/vcs.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
</component>
</project>

5
.prettierrc Normal file
View File

@ -0,0 +1,5 @@
{
"jsxSingleQuote": false,
"singleQuote": true,
"tabWidth": 2
}

124
BUILD.bazel Normal file
View File

@ -0,0 +1,124 @@
load("@bazel_gazelle//:def.bzl", "gazelle")
load("@io_bazel_rules_go//proto:compiler.bzl", "go_proto_compiler")
load("@io_bazel_rules_go//go:def.bzl", "nogo")
exports_files([
"BUILD",
"WORKSPACE",
])
# gazelle:prefix peridot.resf.org
# gazelle:exclude google
# gazelle:exclude vendor/peridot.resf.org
# gazelle:exclude vendor/google.golang.org
# gazelle:exclude vendor/github.com/golang/protobuf
# gazelle:exclude vendor/golang.org/x/net
# gazelle:exclude vendor/github.com/ProtonMail/go-crypto
# gazelle:go_grpc_compilers //:go_apiv2,//:go_grpc,//:go_validate,@com_github_grpc_ecosystem_grpc_gateway_v2//protoc-gen-grpc-gateway:go_gen_grpc_gateway
# gazelle:resolve go github.com/grpc-ecosystem/grpc-gateway/v2/runtime @com_github_grpc_ecosystem_grpc_gateway_v2//runtime:go_default_library
# gazelle:resolve go github.com/grpc-ecosystem/grpc-gateway/v2/utilities @com_github_grpc_ecosystem_grpc_gateway_v2//utilities:go_default_library
# gazelle:resolve go github.com/envoyproxy/protoc-gen-validate/validate @com_envoyproxy_protoc_gen_validate//validate:validate_go_proto
# gazelle:resolve go github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options @com_github_grpc_ecosystem_grpc_gateway_v2//protoc-gen-openapiv2/options:options_go_proto
# gazelle:resolve proto validate/validate.proto @com_envoyproxy_protoc_gen_validate//validate:validate_proto
# gazelle:resolve proto go validate/validate.proto @com_envoyproxy_protoc_gen_validate//validate:validate_go_proto
# gazelle:resolve proto protoc-gen-openapiv2/options/annotations.proto @com_github_grpc_ecosystem_grpc_gateway_v2//protoc-gen-openapiv2/options:options_proto
# gazelle:resolve proto go protoc-gen-openapiv2/options/annotations.proto @com_github_grpc_ecosystem_grpc_gateway_v2//protoc-gen-openapiv2/options:options_go_proto
# gazelle:resolve proto protoc-gen-openapiv2/options/openapiv2.proto @com_github_grpc_ecosystem_grpc_gateway_v2//protoc-gen-openapiv2/options:options_proto
# gazelle:resolve proto go protoc-gen-openapiv2/options/openapiv2.proto @com_github_grpc_ecosystem_grpc_gateway_v2//protoc-gen-openapiv2/options:options_go_proto
gazelle(
name = "gazelle",
)
nogo(
name = "nogo",
config = "nogo.json",
vet = True,
visibility = ["//visibility:public"],
deps = [
"@org_golang_x_tools//go/analysis/passes/asmdecl",
"@org_golang_x_tools//go/analysis/passes/assign",
"@org_golang_x_tools//go/analysis/passes/composite",
"@org_golang_x_tools//go/analysis/passes/copylock",
"@org_golang_x_tools//go/analysis/passes/httpresponse",
"@org_golang_x_tools//go/analysis/passes/loopclosure",
"@org_golang_x_tools//go/analysis/passes/lostcancel",
"@org_golang_x_tools//go/analysis/passes/shift",
"@org_golang_x_tools//go/analysis/passes/stdmethods",
"@org_golang_x_tools//go/analysis/passes/structtag",
"@org_golang_x_tools//go/analysis/passes/tests",
"@org_golang_x_tools//go/analysis/passes/unreachable",
"@org_golang_x_tools//go/analysis/passes/unsafeptr",
"@org_golang_x_tools//go/analysis/passes/unusedresult",
],
)
go_proto_compiler(
name = "go_apiv2",
options = [
"paths=source_relative",
],
plugin = "@org_golang_google_protobuf//cmd/protoc-gen-go",
suffix = ".pb.go",
visibility = ["//visibility:public"],
deps = [
"@com_github_golang_protobuf//proto:go_default_library",
"@io_bazel_rules_go//proto/wkt:any_go_proto",
"@io_bazel_rules_go//proto/wkt:api_go_proto",
"@io_bazel_rules_go//proto/wkt:compiler_plugin_go_proto",
"@io_bazel_rules_go//proto/wkt:descriptor_go_proto",
"@io_bazel_rules_go//proto/wkt:duration_go_proto",
"@io_bazel_rules_go//proto/wkt:empty_go_proto",
"@io_bazel_rules_go//proto/wkt:field_mask_go_proto",
"@io_bazel_rules_go//proto/wkt:source_context_go_proto",
"@io_bazel_rules_go//proto/wkt:struct_go_proto",
"@io_bazel_rules_go//proto/wkt:timestamp_go_proto",
"@io_bazel_rules_go//proto/wkt:type_go_proto",
"@io_bazel_rules_go//proto/wkt:wrappers_go_proto",
"@org_golang_google_protobuf//reflect/protoreflect:go_default_library",
"@org_golang_google_protobuf//runtime/protoimpl:go_default_library",
"@org_golang_google_protobuf//types/descriptorpb:go_default_library",
"@org_golang_google_protobuf//types/known/timestamppb:go_default_library",
"@org_golang_google_protobuf//types/known/wrapperspb:go_default_library",
],
)
go_proto_compiler(
name = "go_grpc",
options = [
"paths=source_relative",
],
plugin = "@org_golang_google_grpc_cmd_protoc_gen_go_grpc//:protoc-gen-go-grpc",
suffix = "_grpc.pb.go",
visibility = ["//visibility:public"],
deps = [
"@io_bazel_rules_go//proto/wkt:any_go_proto",
"@io_bazel_rules_go//proto/wkt:api_go_proto",
"@io_bazel_rules_go//proto/wkt:compiler_plugin_go_proto",
"@io_bazel_rules_go//proto/wkt:descriptor_go_proto",
"@io_bazel_rules_go//proto/wkt:duration_go_proto",
"@io_bazel_rules_go//proto/wkt:empty_go_proto",
"@io_bazel_rules_go//proto/wkt:field_mask_go_proto",
"@io_bazel_rules_go//proto/wkt:source_context_go_proto",
"@io_bazel_rules_go//proto/wkt:struct_go_proto",
"@io_bazel_rules_go//proto/wkt:timestamp_go_proto",
"@io_bazel_rules_go//proto/wkt:type_go_proto",
"@io_bazel_rules_go//proto/wkt:wrappers_go_proto",
"@org_golang_google_grpc//:go_default_library",
"@org_golang_google_grpc//codes:go_default_library",
"@org_golang_google_grpc//status:go_default_library",
],
)
go_proto_compiler(
name = "go_validate",
options = [
"lang=go",
],
plugin = "@com_envoyproxy_protoc_gen_validate//:protoc-gen-validate",
suffix = ".pb.validate.go",
valid_archive = False,
visibility = ["//visibility:public"],
deps = [
"@org_golang_google_protobuf//types/known/anypb",
],
)

16
CONTRIBUTORS Normal file
View File

@ -0,0 +1,16 @@
Project lead:
Mustafa Gezen <mustafa@ctrliq.com>, <mustafa@ciq.co>, <mustafa@rockylinux.org>, <mustafa@gezen.no>
Maintainers:
Mustafa Gezen <mustafa@ctrliq.com>, <mustafa@ciq.co>, <mustafa@rockylinux.org>, <mustafa@gezen.no>
Louis Abel <label@rockylinux.org>
Contributors:
Mustafa Gezen <mustafa@ctrliq.com>, <mustafa@ciq.co>, <mustafa@rockylinux.org>, <mustafa@gezen.no>
John Frey <jfrey@ciq.co>
Louis Abel <label@rockylinux.org>
Neil Hanlon <nhanlon@ciq.co>, <neil@resf.org>
Skip Grube <sgrube@ciq.co>, <skip@rockylinux.org>
Sherif Nagy <sherif@rockylinux.org>
Gregory Kurtzer <gmk@ciq.co>, <gmk@resf.org>

2
COPYRIGHT Normal file
View File

@ -0,0 +1,2 @@
Rocky Enterprise Software Foundation, Inc.
Ctrl IQ, Inc.

30
LICENSE Normal file
View File

@ -0,0 +1,30 @@
Copyright (c) All respective contributors to the Peridot Project. All rights reserved.
Copyright (c) 2021-2022 Rocky Enterprise Software Foundation, Inc. All rights reserved.
Copyright (c) 2021-2022 Ctrl IQ, Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

55
README.md Normal file
View File

@ -0,0 +1,55 @@
# distro-tools
Cloud-native build and release tools tailored to building, releasing and maintaining Linux distributions and forks
## Structure
__Other components pending__
* publisher - `Composer for Peridot (currently only includes legacy mode)`
* peridot - `Modern build system`
* secparse - `Errata mirroring and publishing platform`
* ui - `Product Errata UI`
* utils - `Common utilities`
* modulemd - `Modulemd parser in Go`
## Development
Before the setup install `jq`, `bazelisk`, `docker` and `kubectl`.
A local Kubernetes cluster is also required. Docker Desktop is a good solution.
#### Initial setup (will soon be replaced by one command dev cluster)
```bash
# In the directory where you downloaded istio
bin/istioctl install --set profile=default --set hub=docker.io/querycapistio --set tag=1.12.1 -y
# On aarch64 (ex. M1 Mac) only and add arm64 to list of preferred schedule archs
# Run this while install is running
kubectl -n istio-system edit deployment istio-ingressgateway
sudo hack/deploy_dev_registry
hack/setup_external_dev_services
# Run `kubectl get svc` and add the port of postgres-postgresql to your rc file
# Example:
# postgres-postgresql NodePort 10.102.68.75 <none> 5432:32442/TCP 3m32s
# export POSTGRES_PORT="32442"
hack/setup_k8s_dev_env
git clone https://github.com/temporalio/temporal /tmp/temporal && pushd /tmp/temporal && make temporal-sql-tool && popd && hack/setup_dev_temporal /tmp/temporal
# Sometimes the namespace registration may fail because
# Temporal tools CrashLooped before we could run the migrations.
# Run `kubectl delete pods -l "app.kubernetes.io/name=temporal"` and then re-run
# `kubectl exec -it services/temporal-admintools -- tctl --namespace default namespace re`
hack/setup_base_internal_services
# For the cert, mkcert is recommended (mkcert.dev)
# Add default cert using `kubectl -n istio-system create secret tls default-cert --cert=cert.pem --key=cert.key`
# Create the Istio gateway
bazel run //infrastructure/istio-dev
```
Running `./hack/govendor` should create the necessary structure for development
For best experience use IntelliJ+Bazel but `govendor` creates structure that is compatible with all other Go tools
#### Auto generate (only) BUILD files for Go
`bazel run //:gazelle`
#### Vendor Go dependencies
`./hack/govendor`
#### Run UI in development mode
`ibazel run //TARGET:TARGET.server` - example: `ibazel run //secparse/ui:secparse.server`
#### Find UI server targets
`bazel query 'attr(tags, "byc_frontend_server", //...)'`

218
WORKSPACE Normal file
View File

@ -0,0 +1,218 @@
workspace(
name = "peridot",
managed_directories = {"@npm": ["node_modules"]},
)
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
# --start python--
load("//wrksp:python_download.bzl", "python_download")
python_download()
load("//wrksp:python_deps.bzl", "python_deps")
python_deps()
# --end python--
http_archive(
name = "com_google_protobuf",
sha256 = "3bd7828aa5af4b13b99c191e8b1e884ebfa9ad371b0ce264605d347f135d2568",
strip_prefix = "protobuf-3.19.4",
urls = [
"https://mirror.bazel.build/github.com/protocolbuffers/protobuf/archive/v3.19.4.tar.gz",
"https://github.com/protocolbuffers/protobuf/archive/v3.19.4.tar.gz",
],
)
load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps")
protobuf_deps()
http_archive(
name = "io_bazel_rules_go",
sha256 = "d6b2513456fe2229811da7eb67a444be7785f5323c6708b38d851d2b51e54d83",
urls = [
"https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.30.0/rules_go-v0.30.0.zip",
"https://github.com/bazelbuild/rules_go/releases/download/v0.30.0/rules_go-v0.30.0.zip",
],
)
http_archive(
name = "bazel_gazelle",
sha256 = "de69a09dc70417580aabf20a28619bb3ef60d038470c7cf8442fafcf627c21cb",
urls = [
"https://mirror.bazel.build/github.com/bazelbuild/bazel-gazelle/releases/download/v0.24.0/bazel-gazelle-v0.24.0.tar.gz",
"https://github.com/bazelbuild/bazel-gazelle/releases/download/v0.24.0/bazel-gazelle-v0.24.0.tar.gz",
],
)
load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies")
load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies", "go_repository")
go_rules_dependencies()
go_register_toolchains(
nogo = "@peridot//:nogo",
version = "1.17.7",
)
go_repository(
name = "org_golang_google_grpc",
build_file_proto_mode = "disable",
importpath = "google.golang.org/grpc",
sum = "h1:weqSxi/TMs1SqFRMHCtBgXRs8k3X39QIDEZ0pRcttUg=",
version = "v1.44.0",
)
go_repository(
name = "org_golang_x_net",
importpath = "golang.org/x/net",
sum = "h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk=",
version = "v0.0.0-20220127200216-cd36cc0744dd",
)
go_repository(
name = "org_golang_x_text",
importpath = "golang.org/x/text",
sum = "h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=",
version = "v0.3.0",
)
go_repository(
name = "com_github_ProtonMail_go_crypto",
importpath = "github.com/ProtonMail/go-crypto",
sum = "h1:J2FzIrXN82q5uyUraeJpLIm7U6PffRwje2ORho5yIik=",
version = "v0.0.0-20220113124808-70ae35bab23f",
patches = [
"//patches:0001-Key-ID-subpacket-should-not-be-hashed-or-critical-fo.patch",
],
patch_args = ["-p1"],
)
go_repository(
name = "org_golang_x_oauth2",
build_directives = [
"gazelle:resolve go cloud.google.com/go/compute/metadata @com_google_cloud_go//compute/metadata",
],
importpath = "golang.org/x/oauth2",
sum = "h1:pkQiBZBvdos9qq4wBAHqlzuZHEXo07pqV06ef90u1WI=",
version = "v0.0.0-20210514164344-f6687ab2804c",
)
gazelle_dependencies()
load("@io_bazel_rules_go//extras:embed_data_deps.bzl", "go_embed_data_dependencies")
go_embed_data_dependencies()
http_archive(
name = "build_bazel_rules_nodejs",
sha256 = "8f5f192ba02319254aaf2cdcca00ec12eaafeb979a80a1e946773c520ae0a2c9",
urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/3.7.0/rules_nodejs-3.7.0.tar.gz"],
)
load("@build_bazel_rules_nodejs//:index.bzl", "node_repositories", "yarn_install")
node_repositories(
node_version = "16.2.0",
package_json = ["//:package.json"],
yarn_version = "1.22.10",
)
yarn_install(
name = "npm",
package_json = "//:package.json",
yarn_lock = "//:yarn.lock",
)
# --start docker--
load("//wrksp:docker_download.bzl", "docker_download")
docker_download()
load("//wrksp:docker_deps.bzl", "docker_deps")
docker_deps()
# --end docker--
# --start openapitools--
load("//wrksp:openapitools_download.bzl", "openapitools_download")
openapitools_download()
load("//wrksp:openapitools_deps.bzl", "openapitools_deps")
openapitools_deps()
# --end openapitools--
# --start grpc_gateway--
http_archive(
name = "com_github_grpc_ecosystem_grpc_gateway_v2",
sha256 = "c405cd8f1fb54761933c20be2ad02cce4f9a498d7bdb92a5d3789704884b8360",
strip_prefix = "grpc-gateway-2.7.3",
urls = [
"https://github.com/grpc-ecosystem/grpc-gateway/archive/refs/tags/v2.7.3.tar.gz",
],
)
load("@com_github_grpc_ecosystem_grpc_gateway_v2//:repositories.bzl", "go_repositories")
go_repositories()
# --end grpc_gateway--
# --start protoc_gen_validate--
http_archive(
name = "com_envoyproxy_protoc_gen_validate",
sha256 = "51ba05210a1a2940530455e01c010daa26d504f4b14855a452716772ea39090c",
strip_prefix = "protoc-gen-validate-0.6.3",
urls = [
"https://github.com/envoyproxy/protoc-gen-validate/archive/v0.6.3.tar.gz",
],
)
load("@com_envoyproxy_protoc_gen_validate//:dependencies.bzl", "go_third_party")
go_third_party()
# --end protoc_gen_validate--
# --start jsonnet--
http_archive(
name = "io_bazel_rules_jsonnet",
sha256 = "d20270872ba8d4c108edecc9581e2bb7f320afab71f8caa2f6394b5202e8a2c3",
strip_prefix = "rules_jsonnet-0.4.0",
urls = ["https://github.com/bazelbuild/rules_jsonnet/archive/0.4.0.tar.gz"],
)
load("@io_bazel_rules_jsonnet//jsonnet:jsonnet.bzl", "jsonnet_repositories")
jsonnet_repositories()
load("@google_jsonnet_go//bazel:repositories.bzl", "jsonnet_go_repositories")
jsonnet_go_repositories()
load("@google_jsonnet_go//bazel:deps.bzl", "jsonnet_go_dependencies")
jsonnet_go_dependencies()
# --end jsonnet--
# --start atlassian--
load("//wrksp:atlassian_download.bzl", "atlassian_download")
atlassian_download()
load("//wrksp:atlassian_deps.bzl", "atlassian_deps")
atlassian_deps()
# --end atlassian--
new_local_repository(
name = "raw_ts_library",
build_file = "//rules_raw_ts_library:BUILD",
path = "rules_raw_ts_library",
)
load("//bases/bazel:containers.bzl", "containers")
containers()

0
bases/BUILD.bazel Normal file
View File

0
bases/bazel/BUILD Normal file
View File

View File

@ -0,0 +1,18 @@
load("@io_bazel_rules_docker//container:container.bzl", "container_pull")
load("//bases/bazel/node:defs.bzl", "node_base")
load("//bases/bazel/go:defs.bzl", "go_base")
load("//bases/build:defs.bzl", "build_base")
def rocky8():
container_pull(
name = "rocky8",
registry = "quay.io",
repository = "rockylinux/rockylinux",
digest = "sha256:f0d7460b97156f6c8ea2ae73152bc11fe410d272387d60ddff36dfcea22ef689", # 8.4
)
def containers():
rocky8()
node_base()
go_base()
build_base()

36
bases/bazel/go/BUILD Normal file
View File

@ -0,0 +1,36 @@
load("@io_bazel_rules_docker//container:container.bzl", "container_image")
container_image(
name = "go",
base = select({
"//platforms:arm64": "@go_base_arm64//image",
"//platforms:x86_64": "@go_base_amd64//image",
"//platforms:s390x": "@go_base_s390x//image",
"//platforms:ppc64le": "@go_base_ppc64le//image",
}),
visibility = ["//visibility:public"],
)
container_image(
name = "go_arm64",
base = "@go_base_arm64//image",
visibility = ["//visibility:public"],
)
container_image(
name = "go_amd64",
base = "@go_base_amd64//image",
visibility = ["//visibility:public"],
)
container_image(
name = "go_s390x",
base = "@go_base_s390x//image",
visibility = ["//visibility:public"],
)
container_image(
name = "go_ppc64le",
base = "@go_base_ppc64le//image",
visibility = ["//visibility:public"],
)

32
bases/bazel/go/defs.bzl Normal file
View File

@ -0,0 +1,32 @@
load("@io_bazel_rules_docker//container:container.bzl", "container_pull")
load("//bases:defs.bzl", "ACTIVE_VERSION")
def go_base():
container_pull(
name = "go_base_amd64",
architecture = "amd64",
registry = "quay.io",
repository = "peridot/bazel-go",
tag = ACTIVE_VERSION,
)
container_pull(
name = "go_base_arm64",
architecture = "arm64",
registry = "quay.io",
repository = "peridot/bazel-go",
tag = ACTIVE_VERSION,
)
container_pull(
name = "go_base_s390x",
architecture = "s390x",
registry = "quay.io",
repository = "peridot/bazel-go",
tag = ACTIVE_VERSION,
)
container_pull(
name = "go_base_ppc64le",
architecture = "ppc64le",
registry = "quay.io",
repository = "peridot/bazel-go",
tag = ACTIVE_VERSION,
)

10
bases/bazel/node/BUILD Normal file
View File

@ -0,0 +1,10 @@
load("@io_bazel_rules_docker//container:container.bzl", "container_image")
container_image(
name = "node",
base = select({
"//platforms:arm64": "@node_base_arm64//image",
"//platforms:x86_64": "@node_base_amd64//image",
}),
visibility = ["//visibility:public"],
)

18
bases/bazel/node/defs.bzl Normal file
View File

@ -0,0 +1,18 @@
load("@io_bazel_rules_docker//container:container.bzl", "container_pull")
load("//bases:defs.bzl", "ACTIVE_VERSION")
def node_base():
container_pull(
name = "node_base_amd64",
architecture = "amd64",
registry = "quay.io",
repository = "peridot/bazel-node",
tag = ACTIVE_VERSION,
)
container_pull(
name = "node_base_arm64",
architecture = "arm64",
registry = "quay.io",
repository = "peridot/bazel-node",
tag = ACTIVE_VERSION,
)

36
bases/build/BUILD Normal file
View File

@ -0,0 +1,36 @@
load("@io_bazel_rules_docker//container:container.bzl", "container_image")
container_image(
name = "build_arm64",
base = "@build_base_arm64//image",
visibility = ["//visibility:public"],
)
container_image(
name = "build_amd64",
base = "@build_base_amd64//image",
visibility = ["//visibility:public"],
)
container_image(
name = "build_s390x",
base = "@build_base_s390x//image",
visibility = ["//visibility:public"],
)
container_image(
name = "build_ppc64le",
base = "@build_base_ppc64le//image",
visibility = ["//visibility:public"],
)
container_image(
name = "build",
base = select({
"//platforms:arm64": "@build_base_arm64//image",
"//platforms:x86_64": "@build_base_amd64//image",
"//platforms:s390x": "@build_base_s390x//image",
"//platforms:ppc64le": "@build_base_ppc64le//image",
}),
visibility = ["//visibility:public"],
)

32
bases/build/defs.bzl Normal file
View File

@ -0,0 +1,32 @@
load("@io_bazel_rules_docker//container:container.bzl", "container_pull")
load("//bases:defs.bzl", "ACTIVE_VERSION")
def build_base():
container_pull(
name = "build_base_amd64",
architecture = "amd64",
registry = "quay.io",
repository = "peridot/build-base",
tag = ACTIVE_VERSION,
)
container_pull(
name = "build_base_arm64",
architecture = "arm64",
registry = "quay.io",
repository = "peridot/build-base",
tag = ACTIVE_VERSION,
)
container_pull(
name = "build_base_s390x",
architecture = "s390x",
registry = "quay.io",
repository = "peridot/build-base",
tag = ACTIVE_VERSION,
)
container_pull(
name = "build_base_ppc64le",
architecture = "ppc64le",
registry = "quay.io",
repository = "peridot/build-base",
tag = ACTIVE_VERSION,
)

1
bases/defs.bzl Normal file
View File

@ -0,0 +1 @@
ACTIVE_VERSION = "v0.3.10"

View File

@ -0,0 +1,23 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
load("@rules_proto//proto:defs.bzl", "proto_library")
load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library")
proto_library(
name = "bazelbuild_proto",
srcs = ["build.proto"],
visibility = ["//visibility:public"],
)
go_proto_library(
name = "bazelbuild_go_proto",
importpath = "bazel.build/protobuf",
proto = ":bazelbuild_proto",
visibility = ["//visibility:public"],
)
go_library(
name = "protobuf",
embed = [":bazelbuild_go_proto"],
importpath = "bazel.build/protobuf",
visibility = ["//visibility:public"],
)

View File

@ -0,0 +1,534 @@
// Copyright 2014 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// This file contains the protocol buffer representation of a build
// file or 'blaze query --output=proto' call.
syntax = "proto2";
package blaze_query;
// option cc_api_version = 2;
// option java_api_version = 1;
option java_package = "com.google.devtools.build.lib.query2.proto.proto2api";
option go_package = "bazel.build/protobuf;bazelbuild";
message License {
repeated string license_type = 1;
repeated string exception = 2;
}
message StringDictEntry {
required string key = 1;
required string value = 2;
}
message LabelDictUnaryEntry {
required string key = 1;
required string value = 2;
}
message LabelListDictEntry {
required string key = 1;
repeated string value = 2;
}
message LabelKeyedStringDictEntry {
required string key = 1;
required string value = 2;
}
message StringListDictEntry {
required string key = 1;
repeated string value = 2;
}
// Represents an entry attribute of a Fileset rule in a build file.
message FilesetEntry {
// Indicates what to do when a source file is actually a symlink.
enum SymlinkBehavior {
COPY = 1;
DEREFERENCE = 2;
}
// The label pointing to the source target where files are copied from.
required string source = 1;
// The relative path within the fileset rule where files will be mapped.
required string destination_directory = 2;
// Whether the files= attribute was specified. This is necessary because
// no files= attribute and files=[] mean different things.
optional bool files_present = 7;
// A list of file labels to include from the source directory.
repeated string file = 3;
// If this is a fileset entry representing files within the rule
// package, this lists relative paths to files that should be excluded from
// the set. This cannot contain values if 'file' also has values.
repeated string exclude = 4;
// This field is optional because there will be some time when the new
// PB is used by tools depending on blaze query, but the new blaze version
// is not yet released.
// TODO(bazel-team): Make this field required once a version of Blaze is
// released that outputs this field.
optional SymlinkBehavior symlink_behavior = 5 [default = COPY];
// The prefix to strip from the path of the files in this FilesetEntry. Note
// that no value and the empty string as the value mean different things here.
optional string strip_prefix = 6;
}
// A rule attribute. Each attribute must have a type and one of the various
// value fields populated - for the most part.
//
// Attributes of BOOLEAN and TRISTATE type may set all of the int, bool, and
// string values for backwards compatibility with clients that expect them to
// be set.
//
// Attributes of INTEGER, STRING, LABEL, LICENSE, BOOLEAN, and TRISTATE type
// may set *none* of the values. This can happen if the Attribute message is
// prepared for a client that doesn't support SELECTOR_LIST, but the rule has
// a selector list value for the attribute. (Selector lists for attributes of
// other types--the collection types--are handled differently when prepared
// for such a client. The possible collection values are gathered together
// and flattened.)
//
// By checking the type, the appropriate value can be extracted - see the
// comments on each type for the associated value. The order of lists comes
// from the blaze parsing. If an attribute is of a list type, the associated
// list should never be empty.
message Attribute {
reserved 12, 16;
// Indicates the type of attribute.
enum Discriminator {
INTEGER = 1; // int_value
STRING = 2; // string_value
LABEL = 3; // string_value
OUTPUT = 4; // string_value
STRING_LIST = 5; // string_list_value
LABEL_LIST = 6; // string_list_value
OUTPUT_LIST = 7; // string_list_value
DISTRIBUTION_SET = 8; // string_list_value - order is unimportant
LICENSE = 9; // license
STRING_DICT = 10; // string_dict_value
FILESET_ENTRY_LIST = 11; // fileset_list_value
LABEL_LIST_DICT = 12; // label_list_dict_value
STRING_LIST_DICT = 13; // string_list_dict_value
BOOLEAN = 14; // int, bool and string value
TRISTATE = 15; // tristate, int and string value
INTEGER_LIST = 16; // int_list_value
UNKNOWN = 18; // unknown type, use only for build extensions
LABEL_DICT_UNARY = 19; // label_dict_unary_value
SELECTOR_LIST = 20; // selector_list
LABEL_KEYED_STRING_DICT = 21; // label_keyed_string_dict
DEPRECATED_STRING_DICT_UNARY = 17;
}
// Values for the TriState field type.
enum Tristate {
NO = 0;
YES = 1;
AUTO = 2;
}
message SelectorEntry {
reserved 12;
// The key of the selector entry. At this time, this is the label of a
// config_setting rule, or the pseudo-label "//conditions:default".
optional string label = 1;
// True if the entry's value is the default value for the type as a
// result of the condition value being specified as None (ie:
// {"//condition": None}).
optional bool is_default_value = 16;
// Exactly one of the following fields (except for glob_criteria) must be
// populated - note that the BOOLEAN and TRISTATE caveat in Attribute's
// comment does not apply here. The type field in the SelectorList
// containing this entry indicates which of these fields is populated,
// in accordance with the comments on Discriminator enum values above.
// (To be explicit: BOOLEAN populates the boolean_value field and TRISTATE
// populates the tristate_value field.)
optional int32 int_value = 2;
optional string string_value = 3;
optional bool boolean_value = 4;
optional Tristate tristate_value = 5;
repeated string string_list_value = 6;
optional License license = 7;
repeated StringDictEntry string_dict_value = 8;
repeated FilesetEntry fileset_list_value = 9;
repeated LabelListDictEntry label_list_dict_value = 10;
repeated StringListDictEntry string_list_dict_value = 11;
repeated int32 int_list_value = 13;
repeated LabelDictUnaryEntry label_dict_unary_value = 15;
repeated LabelKeyedStringDictEntry label_keyed_string_dict_value = 17;
repeated bytes DEPRECATED_string_dict_unary_value = 14;
}
message Selector {
// The list of (label, value) pairs in the map that defines the selector.
// At this time, this cannot be empty, i.e. a selector has at least one
// entry.
repeated SelectorEntry entries = 1;
// Whether or not this has any default values.
optional bool has_default_value = 2;
// The error message when no condition matches.
optional string no_match_error = 3;
}
message SelectorList {
// The type that this selector list evaluates to, and the type that each
// selector in the list evaluates to. At this time, this cannot be
// SELECTOR_LIST, i.e. selector lists do not nest.
optional Discriminator type = 1;
// The list of selector elements in this selector list. At this time, this
// cannot be empty, i.e. a selector list is never empty.
repeated Selector elements = 2;
}
// The name of the attribute
required string name = 1;
// Whether the attribute was explicitly specified
optional bool explicitly_specified = 13;
// If this attribute has a string value or a string list value, then this
// may be set to indicate that the value may be treated as a label that
// isn't a dependency of this attribute's rule.
optional bool nodep = 20;
// The type of attribute. This message is used for all of the different
// attribute types so the discriminator helps for figuring out what is
// stored in the message.
required Discriminator type = 2;
// If this attribute has an integer value this will be populated.
// Boolean and TriState also use this field as [0,1] and [-1,0,1]
// for [false, true] and [auto, no, yes] respectively.
optional int32 int_value = 3;
// If the attribute has a string value this will be populated. Label and
// path attributes use this field as the value even though the type may
// be LABEL or something else other than STRING.
optional string string_value = 5;
// If the attribute has a boolean value this will be populated.
optional bool boolean_value = 14;
// If the attribute is a Tristate value, this will be populated.
optional Tristate tristate_value = 15;
// The value of the attribute has a list of string values (label and path
// note from STRING applies here as well).
repeated string string_list_value = 6;
// If this is a license attribute, the license information is stored here.
optional License license = 7;
// If this is a string dict, each entry will be stored here.
repeated StringDictEntry string_dict_value = 8;
// If the attribute is part of a Fileset, the fileset entries are stored in
// this field.
repeated FilesetEntry fileset_list_value = 9;
// If this is a label list dict, each entry will be stored here.
repeated LabelListDictEntry label_list_dict_value = 10;
// If this is a string list dict, each entry will be stored here.
repeated StringListDictEntry string_list_dict_value = 11;
// The value of the attribute has a list of int32 values
repeated int32 int_list_value = 17;
// If this is a label dict unary, each entry will be stored here.
repeated LabelDictUnaryEntry label_dict_unary_value = 19;
// If this is a label-keyed string dict, each entry will be stored here.
repeated LabelKeyedStringDictEntry label_keyed_string_dict_value = 22;
// If this attribute's value is an expression containing one or more select
// expressions, then its type is SELECTOR_LIST and a SelectorList will be
// stored here.
optional SelectorList selector_list = 21;
repeated bytes DEPRECATED_string_dict_unary_value = 18;
}
// A rule instance (e.g., cc_library foo, java_binary bar).
message Rule {
reserved 8, 11;
// The name of the rule (formatted as an absolute label, e.g. //foo/bar:baz).
required string name = 1;
// The rule class (e.g., java_library)
required string rule_class = 2;
// The BUILD file and line number of the location (formatted as
// <absolute_path>:<line_number>:<column_number>) in the rule's package's
// BUILD file where the rule instance was instantiated. The line number will
// be that of a rule invocation or macro call (that in turn invoked a
// rule). See
// https://docs.bazel.build/versions/master/skylark/macros.html#macro-creation
optional string location = 3;
// All of the attributes that describe the rule.
repeated Attribute attribute = 4;
// All of the inputs to the rule (formatted as absolute labels). These are
// predecessors in the dependency graph.
repeated string rule_input = 5;
// All of the outputs of the rule (formatted as absolute labels). These are
// successors in the dependency graph.
repeated string rule_output = 6;
// The set of all "features" inherited from the rule's package declaration.
repeated string default_setting = 7;
// The rule's class's public by default value.
optional bool DEPRECATED_public_by_default = 9;
optional bool DEPRECATED_is_skylark = 10;
// Hash encapsulating the behavior of this Starlark rule. Any change to this
// rule's definition that could change its behavior will be reflected here.
optional string skylark_environment_hash_code = 12;
// The Starlark call stack at the moment the rule was instantiated.
// Each entry has the form "file:line:col: function".
// The outermost stack frame ("<toplevel>", the BUILD file) appears first;
// the frame for the rule function itself is omitted.
// The file name may be relative to package's source root directory.
//
// Requires --proto:instantiation_stack=true.
repeated string instantiation_stack = 13;
// The Starlark call stack for the definition of the rule class of this
// particular rule instance. If empty, either populating the field was not
// enabled on the command line with the --proto:definition_stack flag or the
// rule is a native one.
repeated string definition_stack = 14;
}
// Summary of all transitive dependencies of 'rule,' where each dependent
// rule is included only once in the 'dependency' field. Gives complete
// information to analyze the single build target labeled rule.name,
// including optional location of target in BUILD file.
message RuleSummary {
required Rule rule = 1;
repeated Rule dependency = 2;
optional string location = 3;
}
// A package group. Aside from the name, it contains the list of packages
// present in the group (as specified in the BUILD file).
message PackageGroup {
reserved 4;
// The name of the package group
required string name = 1;
// The list of packages as specified in the BUILD file. Currently this is
// only a list of packages, but some time in the future, there might be
// some type of wildcard mechanism.
repeated string contained_package = 2;
// The list of sub package groups included in this one.
repeated string included_package_group = 3;
}
// An environment group.
message EnvironmentGroup {
// The name of the environment group.
required string name = 1;
// The environments that belong to this group (as labels).
repeated string environment = 2;
// The member environments that rules implicitly support if not otherwise
// specified.
repeated string default = 3;
}
// A file that is an input into the build system.
// Next-Id: 10
message SourceFile {
reserved 7;
// The name of the source file (a label).
required string name = 1;
// The location of the source file. This is a path with a line number and a
// column number not a label in the build system.
optional string location = 2;
// Labels of .bzl (Starlark) files that are transitively loaded in this BUILD
// file. This is present only when the SourceFile represents a BUILD file that
// loaded .bzl files.
// TODO(bazel-team): Rename this field.
repeated string subinclude = 3;
// Labels of package groups that are mentioned in the visibility declaration
// for this source file.
repeated string package_group = 4;
// Labels mentioned in the visibility declaration (including :__pkg__ and
// //visibility: ones)
repeated string visibility_label = 5;
// The package-level features enabled for this package. Only present if the
// SourceFile represents a BUILD file.
repeated string feature = 6;
// License attribute for the file.
optional License license = 8;
// True if the package contains an error. Only present if the SourceFile
// represents a BUILD file.
optional bool package_contains_errors = 9;
}
// A file that is the output of a build rule.
message GeneratedFile {
// The name of the generated file (a label).
required string name = 1;
// The label of the target that generates the file.
required string generating_rule = 2;
// The path, line number, and column number of the output file (not a label).
optional string location = 3;
}
// A target from a blaze query execution. Similar to the Attribute message,
// the Discriminator is used to determine which field contains information.
// For any given type, only one of these can be populated in a single Target.
message Target {
enum Discriminator {
RULE = 1;
SOURCE_FILE = 2;
GENERATED_FILE = 3;
PACKAGE_GROUP = 4;
ENVIRONMENT_GROUP = 5;
}
// The type of target contained in the message.
required Discriminator type = 1;
// If this target represents a rule, the rule is stored here.
optional Rule rule = 2;
// A file that is not generated by the build system (version controlled
// or created by the test harness).
optional SourceFile source_file = 3;
// A generated file that is the output of a rule.
optional GeneratedFile generated_file = 4;
// A package group.
optional PackageGroup package_group = 5;
// An environment group.
optional EnvironmentGroup environment_group = 6;
}
// Container for all of the blaze query results.
message QueryResult {
// All of the targets returned by the blaze query.
repeated Target target = 1;
}
////////////////////////////////////////////////////////////////////////////
// Messages dealing with querying the BUILD language itself. For now, this is
// quite simplistic: Blaze can only tell the names of the rule classes, their
// attributes with their type.
// Information about allowed rule classes for a specific attribute of a rule.
message AllowedRuleClassInfo {
enum AllowedRuleClasses {
ANY = 1; // Any rule is allowed to be in this attribute
SPECIFIED = 2; // Only the explicitly listed rules are allowed
}
required AllowedRuleClasses policy = 1;
// Rule class names of rules allowed in this attribute, e.g "cc_library",
// "py_binary". Only present if the allowed_rule_classes field is set to
// SPECIFIED.
repeated string allowed_rule_class = 2;
}
// This message represents a single attribute of a single rule.
// See docs.bazel.build/versions/master/skylark/lib/attr.html.
message AttributeDefinition {
required string name = 1; // e.g. "name", "srcs"
required Attribute.Discriminator type = 2;
optional bool mandatory = 3;
optional AllowedRuleClassInfo allowed_rule_classes = 4; // type=label*
optional string documentation = 5;
optional bool allow_empty = 6; // type=*_list|*_dict
optional bool allow_single_file = 7; // type=label
optional AttributeValue default =
9; // simple (not computed/late-bound) values only
optional bool executable = 10; // type=label
optional bool configurable = 11;
optional bool nodep =
12; // label-valued edge does not establish a dependency
optional bool cfg_is_host =
13; // edge entails a transition to "host" configuration
}
// An AttributeValue represents the value of an attribute.
// A single field, determined by the attribute type, is populated.
//
// It is used only for AttributeDefinition.default. Attribute and
// SelectorEntry do their own thing for unfortunate historical reasons.
message AttributeValue {
optional int32 int = 1; // type=int|tristate
optional string string = 2; // type=string|label|output
optional bool bool = 3; // type=bool
repeated AttributeValue list = 4; // type=*_list|distrib
repeated DictEntry dict = 5; // type=*_dict
message DictEntry {
required string key = 1;
required AttributeValue value = 2;
}
}
message RuleDefinition {
required string name = 1;
// Only contains documented attributes
repeated AttributeDefinition attribute = 2;
optional string documentation = 3;
// Only for build extensions: label to file that defines the extension
optional string label = 4;
}
message BuildLanguage {
// Only contains documented rule definitions
repeated RuleDefinition rule = 1;
}

View File

@ -0,0 +1,46 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library")
package(default_visibility = ["//visibility:public"])
load("@rules_proto//proto:defs.bzl", "proto_library")
licenses(["notice"])
proto_library(
name = "remoteexecution_proto",
srcs = ["remote_execution.proto"],
deps = [
"//build/bazel/semver:semver_proto",
"@com_google_protobuf//:duration_proto",
"@com_google_protobuf//:timestamp_proto",
"@go_googleapis//google/api:annotations_proto",
"@go_googleapis//google/longrunning:longrunning_proto",
"@go_googleapis//google/rpc:status_proto",
],
)
# keep
go_proto_library(
name = "remoteexecution_go_proto",
compilers = [
"//:go_apiv2",
"//:go_grpc",
],
importpath = "bazel.build/remote/execution/v2",
proto = ":remoteexecution_proto",
deps = [
"//build/bazel/semver:semver_go_proto",
"@go_googleapis//google/api:annotations_go_proto",
"@go_googleapis//google/longrunning:longrunning_go_proto",
"@go_googleapis//google/rpc:status_go_proto",
"@org_golang_google_protobuf//types/known/durationpb",
"@org_golang_google_protobuf//types/known/timestamppb",
],
)
go_library(
name = "execution",
embed = [":remoteexecution_go_proto"],
importpath = "bazel.build/remote/execution/v2",
)

View File

@ -0,0 +1,53 @@
# Node Property Lexicon
This lexicon defines standard property names and values that servers MAY
support in the `NodeProperty` message.
The following standard property `name`s are defined:
* `UnixMode`: This describes the access rights of the file represented by the
node. The value of this must be a string representation of the access mode
bits rendered as a 4-digit octal. Multiple values are not allowed.
Example:
```json
// (Directory proto)
{
"files": [
{
"name": "foo",
"digest": {...},
"node_properties": [
{
"name": "UnixMode",
"value": "4755"
}
]
}
]
}
```
* `MTime`: This describes the last data-modification time of a file represented
by a node. The value of this must be a string encoding this time in the
Timestamp format documented at https://www.ietf.org/rfc/rfc3339.txt. Multiple
values are not allowed.
Example:
```json
// (Directory proto)
{
"files": [
{
"name": "foo",
"digest": {...},
"node_properties": [
{
"name": "MTime",
"value": "2017-01-15T01:30:15.01Z"
}
]
}
]
}
```

View File

@ -0,0 +1,120 @@
# Platform Lexicon
This lexicon defines standard platform property names and values that servers
MAY support in the `Platform` message to facilitate interoperability.
The following standard property `name`s are defined:
* `OSFamily`: This describes the operating system family. Multiple values
are not allowed and an exact match is required.
The following standard values are defined:
- `aix`
- `freebsd`
- `linux`
- `macos`
- `sunos`
- `windows`
Additional values may be defined by the server. For other POSIX systems
the recommendation is to use the output of `uname -s` in lower case.
* `ISA`: This describes the instruction set architecture including
instruction set extensions and versions. Multiple values are allowed. If
multiple values are specified, they are AND-ed together: the worker is
required to support all of the listed values.
The following standard instruction set architecture values are defined:
- `arm-a32` (little endian)
- `arm-a32-be` (big endian)
- `arm-a64` (little endian)
- `arm-a64-be` (big endian)
- `arm-t32` (little endian)
- `arm-t32-be` (big endian)
- `power-isa-be` (big endian)
- `power-isa-le` (little endian)
- `sparc-v9` (big endian)
- `x86-32`
- `x86-64`
The following standard instruction set extension and version values are
defined:
- `arm-neon`
- `arm-sve`
- `arm-vfpv3`
- `arm-vfpv4`
- `armv6`
- `armv7`
- `armv8`
- `x86-avx`
- `x86-avx2`
- `x86-avx-512`
- `x86-sse4.1`
- `x86-sse4.2`
Additional values may be defined by the server. Vendor-neutral names are
recommended.
Clients SHOULD NOT request instruction set extensions or versions without
requesting an instruction set architecture.
Examples with multiple values:
```json
// (Platform proto)
{
"properties": [
{
"name": "ISA",
"value": "x86-64"
},
{
"name": "ISA",
"value": "x86-avx2"
}
]
}
```
```json
// (Platform proto)
{
"properties": [
{
"name": "ISA",
"value": "arm-a64"
},
{
"name": "ISA",
"value": "armv8"
},
{
"name": "ISA",
"value": "arm-sve"
}
]
}
```
```json
// (Platform proto)
{
"properties": [
{
"name": "ISA",
"value": "arm-a32"
},
{
"name": "ISA",
"value": "armv7"
},
{
"name": "ISA",
"value": "arm-vfpv4"
}
]
}
```

File diff suppressed because it is too large Load Diff

25
build/bazel/semver/BUILD Normal file
View File

@ -0,0 +1,25 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library")
package(default_visibility = ["//visibility:public"])
load("@rules_proto//proto:defs.bzl", "proto_library")
licenses(["notice"])
proto_library(
name = "semver_proto",
srcs = ["semver.proto"],
)
go_proto_library(
name = "semver_go_proto",
importpath = "bazel.build/semver",
proto = ":semver_proto",
)
go_library(
name = "semver",
embed = [":semver_go_proto"],
importpath = "bazel.build/semver",
)

View File

@ -0,0 +1,41 @@
// Copyright 2018 The Bazel Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
syntax = "proto3";
package build.bazel.semver;
option csharp_namespace = "Build.Bazel.Semver";
option go_package = "bazel.build/semver;semver";
option java_multiple_files = true;
option java_outer_classname = "SemverProto";
option java_package = "build.bazel.semver";
option objc_class_prefix = "SMV";
// The full version of a given tool.
message SemVer {
// The major version, e.g 10 for 10.2.3.
int32 major = 1;
// The minor version, e.g. 2 for 10.2.3.
int32 minor = 2;
// The patch version, e.g 3 for 10.2.3.
int32 patch = 3;
// The pre-release version. Either this field or major/minor/patch fields
// must be filled. They are mutually exclusive. Pre-release versions are
// assumed to be earlier than any released versions.
string prerelease = 4;
}

11
ci/BUILD Normal file
View File

@ -0,0 +1,11 @@
load("@io_bazel_rules_jsonnet//jsonnet:jsonnet.bzl", "jsonnet_library")
package(default_visibility = ["//visibility:public"])
jsonnet_library(
name = "ci",
srcs = glob([
"**/*.jsonnet",
"**/*.libsonnet",
]),
)

6
ci/bazel.jsonnet Normal file
View File

@ -0,0 +1,6 @@
{
define_project(path)::
{
bazel_path: path
}
}

331
ci/bycdeploy.jsonnet Normal file
View File

@ -0,0 +1,331 @@
local stage = std.extVar('stage');
local origUser = std.extVar('user');
local domainUser = std.extVar('domain_user');
local ociRegistry = std.extVar('oci_registry');
local ociRegistryRepo = std.extVar('oci_registry_repo');
local registry_secret = std.extVar('registry_secret');
local user = if domainUser != 'user-orig' then domainUser else origUser;
local stageNoDash = std.strReplace(stage, '-', '');
local kubernetes = import 'ci/kubernetes.jsonnet';
local db = import 'ci/db.jsonnet';
local mappings = import 'ci/mappings.jsonnet';
local utils = import 'ci/utils.jsonnet';
local labels = {
labels: db.label() + kubernetes.istio_labels(),
};
{
new(info)::
local metadata = {
name: info.name,
namespace: if stageNoDash == 'dev' then '%s-dev' % user else if std.objectHas(info, 'namespace') then info.namespace else info.name,
};
local fixed = kubernetes.fix_metadata(metadata);
local vshost(srv) = '%s-service.%s.svc.cluster.local' % [srv.name, fixed.namespace];
local infolabels = if info.backend then labels else { labels: kubernetes.istio_labels() };
local dbname = (if std.objectHas(info, 'dbname') then info.dbname else info.name);
local env = if std.objectHas(info, 'env') then info.env else [];
local sa_name = '%s-%s-serviceaccount' % [stageNoDash, fixed.name];
local extra_info = {
service_account_name: sa_name,
};
local envs = [stageNoDash];
local services = if std.objectHas(info, 'services') then info.services else
[{ name: '%s-%s-%s' % [metadata.name, port.name, env], port: port.containerPort, portName: port.name, expose: if std.objectHas(port, 'expose') then port.expose else false } for env in envs for port in info.ports];
local nssa = '001-ns-sa.yaml';
local migrate = '002-migrate.yaml';
local deployment = '003-deployment.yaml';
local svcVsDr = '004-svc-vs-dr.yaml';
local custom = '005-custom.yaml';
local legacyDb = if std.objectHas(info, 'legacyDb') then info.legacyDb else false;
local dbPassEnv = {
name: 'DATABASE_PASSWORD',
valueFrom: !utils.local_image,
value: if utils.local_image then 'postgres',
secret: if !utils.local_image then {
name: '%s-database-password' % db.staged_name(dbname),
key: 'password',
},
};
local shouldSecureEndpoint(srv) = if mappings.get_env_from_svc(srv.name) == 'prod' && mappings.is_external(srv.name) then false
else if mappings.should_expose_all(srv.name) then false
else if utils.local_image then false
else if !std.objectHas(srv, 'expose') || !srv.expose then false
else true;
local imagePullSecrets = if registry_secret != 'none' then [registry_secret] else [];
{
[nssa]: std.manifestYamlStream([
kubernetes.define_namespace(metadata.namespace, infolabels),
kubernetes.define_service_account(metadata {
name: '%s-%s' % [stageNoDash, fixed.name],
} + if std.objectHas(info, 'service_account_options') then info.service_account_options else {},
),
]),
[if std.objectHas(info, 'migrate') && info.migrate == true then migrate else null]:
std.manifestYamlStream([
kubernetes.define_service_account(metadata {
name: 'init-db-%s-%s' % [fixed.name, stageNoDash],
}),
kubernetes.define_role_binding(metadata, metadata.name + '-role', [{
kind: 'ServiceAccount',
name: 'init-db-%s-%s-serviceaccount' % [fixed.name, stageNoDash],
namespace: metadata.namespace,
}]),
kubernetes.define_cluster_role_binding(metadata, metadata.name + '-clusterrole', [{
kind: 'ServiceAccount',
name: 'init-db-%s-%s-serviceaccount' % [fixed.name, stageNoDash],
namespace: metadata.namespace,
}]),
kubernetes.define_role(
metadata {
name: 'init-db-%s-%s' % [fixed.name, stageNoDash],
},
[{
apiGroups: [''],
resources: ['secrets'],
verbs: ['create', 'get'],
}]
),
kubernetes.define_cluster_role(
metadata {
name: 'init-db-%s-%s' % [fixed.name, stageNoDash],
},
[{
apiGroups: [''],
resources: ['secrets'],
verbs: ['create', 'get'],
}]
),
kubernetes.define_role_binding(
metadata {
name: 'init-db-%s-%s' % [fixed.name, stageNoDash],
},
'init-db-%s-%s-role' % [fixed.name, stageNoDash],
[{
kind: 'ServiceAccount',
name: 'init-db-%s-%s-serviceaccount' % [fixed.name, stageNoDash],
namespace: fixed.namespace,
}],
),
kubernetes.define_cluster_role_binding(
metadata {
name: 'init-db-%s-%s' % [fixed.name, stageNoDash],
},
'init-db-%s-%s-clusterrole' % [fixed.name, stageNoDash],
[{
kind: 'ServiceAccount',
name: 'init-db-%s-%s-serviceaccount' % [fixed.name, stageNoDash],
namespace: fixed.namespace,
}],
),
if !legacyDb then kubernetes.define_job(metadata { name: 'request-cert' }, kubernetes.request_cdb_certs('initdb%s' % stageNoDash) + {
serviceAccount: '%s-%s-serviceaccount' % [stageNoDash, fixed.name],
}),
if info.migrate == true && dbname != '' then kubernetes.define_job(metadata { name: info.name + '-migrate' }, {
image: if std.objectHas(info, 'migrate_image') && info.migrate_image != null then info.migrate_image else info.image,
tag: if std.objectHas(info, 'migrate_tag') && info.migrate_tag != null then info.migrate_tag else info.tag,
command: if std.objectHas(info, 'migrate_command') && info.migrate_command != null then info.migrate_command else ['/bin/sh'],
serviceAccount: 'init-db-%s-%s-serviceaccount' % [fixed.name, stageNoDash],
imagePullSecrets: imagePullSecrets,
args: if std.objectHas(info, 'migrate_args') && info.migrate_args != null then info.migrate_args else [
'-c',
'export REAL_DSN=`echo $%s | sed -e "s/REPLACEME/${DATABASE_PASSWORD}/g"%s`; /usr/bin/migrate -source file:///migrations -database $REAL_DSN up' % [info.dsn.name, if legacyDb then '' else ' | sed -e "s/postgresql/cockroachdb/g"'],
],
volumes: (if std.objectHas(info, 'volumes') then info.volumes(metadata) else []) + (if !legacyDb then kubernetes.request_cdb_certs_volumes() else []),
initContainers: [
if !legacyDb then kubernetes.request_cdb_certs('%s%s' % [metadata.name, stageNoDash]) + {
serviceAccount: '%s-%s-serviceaccount' % [stageNoDash, fixed.name],
},
{
name: 'initdb',
image: 'quay.io/peridot/initdb:v0.1.4',
command: ['/bin/sh'],
args: ['-c', '/bundle/initdb*'],
volumes: if !legacyDb then kubernetes.request_cdb_certs_volumes(),
env: [
{
name: 'INITDB_TARGET_DB',
value: db.staged_name(dbname),
},
{
name: 'INITDB_PRODUCTION',
value: 'true',
},
{
name: 'INITDB_DATABASE_URL',
value: if legacyDb then db.dsn_legacy('postgres', true) else db.dsn('initdb'),
},
],
},
],
env: [
dbPassEnv,
info.dsn,
],
annotations: {
'sidecar.istio.io/inject': 'false',
},
}) else {},
]),
[deployment]: std.manifestYamlStream([
kubernetes.define_deployment(
metadata,
{
replicas: if std.objectHas(info, 'replicas') then info.replicas else 1,
image: info.image,
tag: info.tag,
command: if std.objectHas(info, 'command') then [info.command] else null,
fsGroup: if std.objectHas(info, 'fsGroup') then info.fsGroup else null,
fsUser: if std.objectHas(info, 'fsUser') then info.fsUser else null,
imagePullSecrets: imagePullSecrets,
labels: db.label(),
annotations: if std.objectHas(info, 'annotations') then info.annotations,
initContainers: if !legacyDb && info.backend then [kubernetes.request_cdb_certs('%s%s' % [metadata.name, stageNoDash]) + {
serviceAccount: '%s-%s-serviceaccount' % [stageNoDash, fixed.name],
}],
volumes: (if std.objectHas(info, 'volumes') then info.volumes(metadata) else []) + (if !legacyDb then kubernetes.request_cdb_certs_volumes() else []),
ports: std.map(function(x) x { expose: null, external: null }, info.ports),
health: if std.objectHas(info, 'health') then info.health,
env: env + (if dbname != '' && info.backend then ([dbPassEnv]) else []) + [
{
name: 'SELF_IDENTITY',
value: 'spiffe://cluster.local/ns/%s/sa/%s-%s-serviceaccount' % [fixed.namespace, stageNoDash, fixed.name],
},
] + [
if std.objectHas(srv, 'expose') && srv.expose then {
name: '%s_PUBLIC_URL' % [std.asciiUpper(std.strReplace(std.strReplace(srv.name, stage, ''), '-', '_'))],
value: 'https://%s' % mappings.get(srv.name, user),
} else null,
for srv in services],
limits: if std.objectHas(info, 'limits') then info.limits,
requests: if std.objectHas(info, 'requests') then info.requests,
args: if std.objectHas(info, 'args') then info.args else [],
serviceAccount: '%s-%s-serviceaccount' % [stageNoDash, fixed.name],
},
),
]),
[svcVsDr]:
std.manifestYamlStream(
[kubernetes.define_service(metadata { name: srv.name }, srv.port, srv.port, portName=srv.portName, selector=metadata.name, env=mappings.get_env_from_svc(srv.name)) for srv in services] +
[kubernetes.define_virtual_service(metadata { name: srv.name + '-internal' }, {
hosts: [vshost(srv)],
gateways: [],
http: [
{
route: [{
destination: {
host: vshost(srv),
subset: mappings.get_env_from_svc(srv.name),
port: {
number: srv.port,
},
},
} + (if std.objectHas(info, 'internal_route_options') then info.internal_route_options else {})],
},
],
},) for srv in services] +
[if std.objectHas(srv, 'expose') && srv.expose then kubernetes.define_virtual_service(
metadata {
name: srv.name,
annotations: {
'external-dns.alpha.kubernetes.io/target': if mappings.is_external(srv.name) then 'ingress.build.resf.org' else 'ingress-internal.build.resf.org',
},
},
{
hosts: [mappings.get(srv.name, user)],
gateways: if mappings.is_external(srv.name) then ['istio-system/base-gateway-public'] else ['istio-system/base-gateway-confidential'],
http: [
{
route: [{
destination: {
host: vshost(srv),
subset: mappings.get_env_from_svc(srv.name),
port: {
number: srv.port,
},
},
} + (if std.objectHas(info, 'external_route_options') then info.external_route_options else {})],
},
],
}
) else null for srv in services] +
[{
apiVersion: 'security.istio.io/v1beta1',
kind: 'RequestAuthentication',
metadata: metadata {
name: srv.name,
},
spec: {
selector: {
matchLabels: {
app: metadata.name,
env: mappings.get_env_from_svc(srv.name),
},
},
// todo(mustafa): Introduce ObsidianProxy to support BeyondCorp
jwtRules: if shouldSecureEndpoint(srv) then [{
issuer: 'https://cloud.google.com/iap',
jwksUri: 'https://www.gstatic.com/iap/verify/public_key-jwk',
fromHeaders: [{ name: 'x-goog-iap-jwt-assertion' }],
}] else [],
},
} for srv in services] +
[{
apiVersion: 'security.istio.io/v1beta1',
kind: 'AuthorizationPolicy',
metadata: metadata {
name: srv.name,
},
spec: {
selector: {
matchLabels: {
app: metadata.name,
env: mappings.get_env_from_svc(srv.name),
},
},
action: 'ALLOW',
rules: [(if shouldSecureEndpoint(srv) then {
from: [],
} else {}) + {
to: [{
operation: {
ports: [std.toString(srv.port)]
}
}]
}],
},
} for srv in services] +
[kubernetes.define_destination_rule(metadata { name: srv.name }, {
host: vshost(srv),
trafficPolicy: {
tls: {
mode: 'ISTIO_MUTUAL',
},
},
subsets: [
{
name: mappings.get_env_from_svc(srv.name),
labels: {
app: metadata.name,
env: mappings.get_env_from_svc(srv.name),
},
},
],
},) for srv in services]
),
[if std.objectHas(info, 'custom_job_items') then custom else null]:
std.manifestYamlStream(if std.objectHas(info, 'custom_job_items') then info.custom_job_items(metadata, extra_info) else [{}]),
},
}

57
ci/db.jsonnet Normal file
View File

@ -0,0 +1,57 @@
local stage = std.extVar('stage');
local origUser = std.extVar('user');
local domainUser = std.extVar('domain_user');
local ociRegistry = std.extVar('oci_registry');
local utils = import 'ci/utils.jsonnet';
local user = if domainUser != 'user-orig' then domainUser else origUser;
{
host()::
'prod-db-cockroachdb-public.cockroachdb.svc.cluster.local',
port()::
'26257',
host_port()::
'%s:%s' % [$.host(), $.port()],
cert(name)::
'/cockroach-certs/client.%s.crt' % name,
key(name)::
'/cockroach-certs/client.%s.key' % name,
ca()::
'/cockroach-certs/ca.crt',
label()::
{ 'cockroachdb-client': 'true' },
obj_label()::
{ labels: $.label() },
staged_name(name)::
'%s%s' % [name, std.strReplace(stage, '-', '')],
dsn_raw(name, password)::
local staged_name = $.staged_name(name);
'postgresql://%s%s@cockroachdb-public.cockroachdb.svc.cluster.local:26257' %
[staged_name, if password then ':byc' else ':REPLACEME'] +
'/%s?sslmode=require&sslcert=/cockroach-certs/client.%s.crt' %
[staged_name, staged_name] +
'&sslkey=/cockroach-certs/client.%s.key&sslrootcert=/cockroach-certs/ca.crt' %
[staged_name],
dsn_legacy(name, no_add=false, ns=null)::
local staged_name = $.staged_name(name);
if utils.local_image then 'postgresql://postgres:postgres@postgres-postgresql.default.svc.cluster.local:5432/%s?sslmode=disable' % staged_name
else 'postgresql://%s%s:REPLACEME@resf-peridot-dev.ctxqgglmfofx.us-east-2.rds.amazonaws.com:5432' %
[if !no_add then (if stage == '-dev' then '%s-dev' % user else if ns != null then ns else name)+'-' else '', if no_add then name else staged_name] +
'/%s?sslmode=disable' %
[if no_add then name else staged_name],
dsn(name)::
$.dsn_raw(name, false),
}

30
ci/frontend.jsonnet Normal file
View File

@ -0,0 +1,30 @@
{
base: [
{
name: 'PORT',
value: '8086',
},
{
name: 'NODE_ENV',
value: 'production',
},
{
name: 'BYC_SECRET',
valueFrom: true,
secret: {
name: 'server',
key: 'byc-secret'
},
},
],
server_env: $.base + [
{
name: 'HYDRA_SECRET',
valueFrom: true,
secret: {
name: 'server',
key: 'hydra-secret'
},
},
]
}

15
ci/google.jsonnet Normal file
View File

@ -0,0 +1,15 @@
local base(info) = {
apiVersion: 'pubsub.cnrm.cloud.google.com/v1beta1',
kind: info.kind,
metadata: info.metadata
} + if std.objectHas(info, 'spec') then info.spec else {};
{
pubsub_topic(info)::
local pubSubTopicInfo = {
kind: 'PubSubTopic',
metadata: info.metadata,
};
base(pubSubTopicInfo)
}

1
ci/istio/BUILD Normal file
View File

@ -0,0 +1 @@
package(default_visibility = ["//visibility:public"])

16
ci/istio/base.libsonnet Normal file
View File

@ -0,0 +1,16 @@
{
KIND_ENVOYFILTER: 'EnvoyFilter',
// Types (unfinished):
// - EnvoyFilter
networking_base(info)::
local envoyFilterTest = std.assertEqual(info.kind, $.KIND_ENVOYFILTER);
local _ = if !envoyFilterTest then non_existing_value;
{
apiVersion: 'networking.istio.io/v1alpha3',
kind: info.kind,
metadata: info.metadata,
} + if std.objectHas(info, 'spec') then info.spec else {},
}

View File

@ -0,0 +1,28 @@
local base = import 'ci/istio/base.libsonnet';
{
FILTER_TYPE_CUSTOM: 'custom',
FILTER_TYPE_REDIRECT: 'redirect',
MATCH_TYPE_BYCDEPLOY: 'bycdeploy',
MATCH_TYPE_ALL: 'all',
envoy_filter(info)::
local filterType = info.type;
local matchType = if filterType != $.FILTER_TYPE_CUSTOM then info.matchType;
local envoyFilterInfo = {
kind: base.KIND_ENVOYFILTER,
metadata: {
name: info.name,
namespace: 'istio-system',
},
spec: if filterType == $.FILTER_TYPE_CUSTOM then info.filter else {
workloadSelector: if matchType == $.MATCH_TYPE_ALL then {}
else if matchType == $.MATCH_TYPE_BYCDEPLOY then {
}
else non_existing_value,
},
};
base(pubSubTopicInfo),
}

631
ci/kubernetes.jsonnet Normal file
View File

@ -0,0 +1,631 @@
local stage = std.extVar('stage');
local tag = std.extVar('tag');
local ociRegistry = std.extVar('oci_registry');
local ociRegistryRepo = std.extVar('oci_registry_repo');
local ociRegistryDocker = std.extVar('oci_registry_docker');
local ociNoNestedSupport = std.extVar('oci_registry_no_nested_support_in_2022_shame_on_you_aws') == 'true';
local site = std.extVar('site');
local arch = std.extVar('arch');
local localEnvironment = std.extVar('local_environment') == '1';
local stageNoDash = std.strReplace(stage, '-', '');
local imagePullPolicy = if stageNoDash == 'dev' then 'Always' else 'IfNotPresent';
local utils = import 'ci/utils.jsonnet';
local defaultEnvs = [
{
name: 'BYC_ENV',
value: stageNoDash,
},
{
name: 'BYC_NS',
valueFrom: true,
field: 'metadata.namespace',
},
{
name: 'BYC_SERVICE_ACCOUNT',
valueFrom: true,
field: 'spec.serviceAccountName',
},
{
name: 'AWS_REGION',
value: 'us-east-2',
},
{
name: 'LOCALSTACK_ENDPOINT',
value: if utils.local_image then 'http://localstack.default.svc.cluster.local:4566' else '',
}
];
local define_env(envsOrig) = std.filter(function(x) x != null, [
if field != null then {
name: field.name,
value: if std.objectHas(field, 'value') then field.value,
valueFrom: if std.objectHas(field, 'valueFrom') && field.valueFrom == true then {
secretKeyRef: if std.objectHas(field, 'secret') then {
name: field.secret.name,
key: field.secret.key,
},
fieldRef: if std.objectHas(field, 'field') then {
fieldPath: field.field,
},
},
}
for field in (envsOrig + defaultEnvs)
]);
local define_volumes(volumes) = [
{
name: vm.name,
persistentVolumeClaim: if std.objectHas(vm, 'pvc') then {
claimName: vm.name,
},
emptyDir: if std.objectHas(vm, 'emptyDir') then {},
secret: if std.objectHas(vm, 'secret') then vm.secret,
configMap: if std.objectHas(vm, 'configMap') then vm.configMap,
}
for vm in volumes
];
local define_volume_mounts(volumes) = [
{
name: vm.name,
mountPath: vm.path,
}
for vm in volumes
];
local define_init_containers(initc_) = std.filter(function(x) x != null, [
if initc != null && std.objectHas(initc, 'name') then {
name: initc.name,
image: initc.image,
imagePullPolicy: imagePullPolicy,
command: if std.objectHas(initc, 'command') then initc.command,
args: if std.objectHas(initc, 'args') then initc.args,
env: define_env(if std.objectHas(initc, 'env') then initc.env else []),
volumeMounts: if std.objectHas(initc, 'volumes') && initc.volumes != null then define_volume_mounts(initc.volumes),
}
for initc in initc_
]);
local default_labels = {
env: stageNoDash
};
local fix_metadata(metadata) = metadata {
namespace: metadata.namespace,
};
local prod() = stage == '-prod';
local dev() = stage == '-dev';
{
// For reference
metadata: {
name: 'empty',
namespace: 'namespace',
annotations: {},
},
// Namespace
define_namespace(name, metadata={})::
{
apiVersion: 'v1',
kind: 'Namespace',
metadata: metadata {
name: name,
},
},
// Deployment
define_deployment(metadataOrig, deporig)::
local _ = std.assertEqual(true, std.objectHas(deporig, 'image'));
local _ = std.assertEqual(true, std.objectHas(deporig, 'tag'));
local metadata = fix_metadata(metadataOrig);
local deployment = deporig {
annotations: if !std.objectHas(deporig, 'annotations') then {} else deporig.annotations,
labels: if !std.objectHas(deporig, 'labels') then default_labels else deporig.labels + default_labels,
volumes: if !std.objectHas(deporig, 'volumes') then [] else deporig.volumes,
imagePulLSecrets: if !std.objectHas(deporig, 'imagePullSecrets') then deporig.imagePullSecrets else deporig.imagePullSecrets,
env: if !std.objectHas(deporig, 'env') then [] else deporig.env,
ports: if !std.objectHas(deporig, 'ports') then [{ containerPort: 80, protocol: 'TCP' }] else deporig.ports,
initContainers: if !std.objectHas(deporig, 'initContainers') then [] else deporig.initContainers,
limits: if !std.objectHas(deporig, 'limits') || deporig.limits == null then { cpu: '0.1', memory: '256M' } else deporig.limits,
requests: if !std.objectHas(deporig, 'requests') || deporig.requests == null then { cpu: '0.001', memory: '128M' } else deporig.requests,
};
{
apiVersion: 'apps/v1',
kind: 'Deployment',
metadata: metadata {
name: metadata.name + '-deployment',
},
spec: {
revisionHistoryLimit: 15,
selector: {
matchLabels: {
app: metadata.name,
env: stageNoDash
},
},
replicas: deployment.replicas,
strategy: {
type: 'RollingUpdate',
rollingUpdate: {
maxSurge: '300%',
maxUnavailable: '0%',
},
},
template: {
metadata: {
annotations: deployment.annotations,
labels: deployment.labels {
app: metadata.name,
env: stageNoDash,
version: deployment.tag,
},
},
spec: {
automountServiceAccountToken: true,
serviceAccountName: if std.objectHas(deployment, 'serviceAccount') then deployment.serviceAccount,
initContainers: if std.objectHas(deployment, 'initContainers') && deployment.initContainers != null then define_init_containers(deployment.initContainers),
securityContext: {
fsGroup: 1000,
},
containers: [
{
image: deployment.image + (if ociNoNestedSupport then '-' else ':') + deployment.tag,
imagePullPolicy: imagePullPolicy,
name: metadata.name,
command: if std.objectHas(deployment, 'command') then deployment.command else null,
args: if std.objectHas(deployment, 'args') then deployment.args else null,
ports: deployment.ports,
env: define_env(deployment.env),
volumeMounts: if std.objectHas(deployment, 'volumes') && deployment.volumes != null then define_volume_mounts(deployment.volumes),
securityContext: {
runAsGroup: if std.objectHas(deployment, 'fsGroup') then deployment.fsGroup else null,
runAsUser: if std.objectHas(deployment, 'fsUser') then deployment.fsUser else null,
},
resources: {
limits: deployment.limits,
requests: deployment.requests,
},
readinessProbe: if std.objectHas(deployment, 'health') && deployment.health != null then {
httpGet: if !std.objectHas(deployment.health, 'grpc') || !deployment.health.grpc then {
path: if std.objectHas(deployment.health, 'path') then deployment.health.path else '/_/healthz',
port: deployment.health.port,
httpHeaders: [
{
name: 'byc-internal-req',
value: 'yes',
},
],
},
exec: if std.objectHas(deployment.health, 'grpc') && deployment.health.grpc then {
command: ["grpc_health_probe", "-connect-timeout=4s", "-v", "-addr=localhost:"+deployment.health.port],
},
initialDelaySeconds: if std.objectHas(deployment.health, 'initialDelaySeconds') then deployment.health.initialDelaySeconds else 1,
periodSeconds: if std.objectHas(deployment.health, 'periodSeconds') then deployment.health.periodSeconds else 3,
timeoutSeconds: if std.objectHas(deployment.health, 'timeoutSeconds') then deployment.health.timeoutSeconds else 5,
successThreshold: if std.objectHas(deployment.health, 'successThreshold') then deployment.health.successThreshold else 1,
failureThreshold: if std.objectHas(deployment.health, 'failureTreshold') then deployment.health.failureTreshold else 30,
} else if std.objectHas(deployment, 'health_tcp') && deployment.health_tcp != null then {
tcpSocket: {
port: deployment.health_tcp.port,
},
initialDelaySeconds: if std.objectHas(deployment.health, 'initialDelaySeconds') then deployment.health.initialDelaySeconds else 5,
periodSeconds: if std.objectHas(deployment.health, 'periodSeconds') then deployment.health.periodSeconds else 5,
},
},
],
affinity: if !std.objectHas(deployment, 'no_anti_affinity') || !deployment.no_anti_affinity then {
podAntiAffinity: {
preferredDuringSchedulingIgnoredDuringExecution: [
{
weight: 99,
podAffinityTerm: {
labelSelector: {
matchExpressions: [
{
key: 'app',
operator: 'In',
values: [
metadata.name,
],
},
],
},
topologyKey: 'kubernetes.io/hostname',
},
},
{
weight: 100,
podAffinityTerm: {
labelSelector: {
matchExpressions: [
{
key: 'app',
operator: 'In',
values: [
metadata.name,
],
},
],
},
topologyKey: 'failure-domain.beta.kubernetes.io/zone',
},
},
],
},
},
restartPolicy: 'Always',
imagePullSecrets: if std.objectHas(deployment, 'imagePullSecrets') && deployment.imagePullSecrets != null then [
{
name: secret,
}
for secret in deployment.imagePullSecrets
],
volumes: if std.objectHas(deployment, 'volumes') && deployment.volumes != null then define_volumes(deployment.volumes),
},
},
},
},
// Ingress
define_ingress(metadataOrig, host, path='/', port=80)::
local metadata = fix_metadata(metadataOrig);
{
apiVersion: 'extensions/v1beta1',
kind: 'Ingress',
metadata: metadata {
name: metadata.name + '-ingress',
},
spec: {
rules: [{
host: host,
http: {
paths: [
{
path: path,
backend: {
serviceName: metadata.name + '-service',
servicePort: port,
},
},
],
},
}],
},
},
// Service
define_service(metadataOrig, externalPort=80, internalPort=80, protocol='TCP', portName='http', selector='', env='canary')::
local metadata = fix_metadata(metadataOrig);
{
apiVersion: 'v1',
kind: 'Service',
metadata: metadata {
name: metadata.name + '-service',
},
spec: {
type: 'ClusterIP',
ports: [{
name: portName,
port: externalPort,
protocol: protocol,
targetPort: internalPort,
}],
selector: {
app: if selector != '' then selector else metadata.name,
env: env,
},
},
},
// Virtual Service
define_virtual_service(metadataOrig, spec)::
local metadata = fix_metadata(metadataOrig);
{
apiVersion: 'networking.istio.io/v1alpha3',
kind: 'VirtualService',
metadata: metadata {
name: metadata.name + '-vs',
},
spec: spec,
},
// Destination rule
define_destination_rule(metadataOrig, spec)::
local metadata = fix_metadata(metadataOrig);
{
apiVersion: 'networking.istio.io/v1alpha3',
kind: 'DestinationRule',
metadata: metadata {
name: metadata.name + '-dsr',
},
spec: spec,
},
// Service entry
define_service_entry(metadataOrig, hosts, ports, resolution, location)::
local metadata = fix_metadata(metadataOrig);
{
apiVersion: 'networking.istio.io/v1alpha3',
kind: 'ServiceEntry',
metadata: metadata {
name: metadata.name + '-se',
},
spec: {
hosts: hosts,
ports: ports,
resolution: resolution,
location: location,
},
},
// Job
define_job(metadataOrig, joborig)::
local metadata = fix_metadata(metadataOrig);
local job = joborig {
env: if !std.objectHas(joborig, 'env') then [] else joborig.env,
labels: if !std.objectHas(joborig, 'labels') then {} else joborig.labels,
annotations: if !std.objectHas(joborig, 'annotations') then {} else joborig.annotations,
initContainers: if !std.objectHas(joborig, 'initContainers') then [] else joborig.initContainers,
volumes: if !std.objectHas(joborig, 'volumes') then [] else joborig.volumes,
args: if !std.objectHas(joborig, 'args') then [] else joborig.args,
};
local name = metadata.name + '-job';
{
apiVersion: 'batch/v1',
kind: 'Job',
metadata: metadata {
name: name,
},
spec: {
ttlSecondsAfterFinished: 120,
template: {
metadata: {
labels: job.labels,
annotations: job.annotations,
},
spec: {
automountServiceAccountToken: true,
serviceAccountName: if std.objectHas(job, 'serviceAccount') then job.serviceAccount,
imagePullSecrets: if std.objectHas(job, 'imagePullSecrets') && job.imagePullSecrets != null then [
{
name: secret,
}
for secret in job.imagePullSecrets
],
initContainers: define_init_containers(job.initContainers),
containers: [{
name: name,
image: job.image + (if ociNoNestedSupport then '-' else ':') + job.tag,
command: if std.objectHas(job, 'command') then job.command else null,
args: job.args,
env: define_env(job.env),
volumeMounts: if std.objectHas(job, 'volumes') && job.volumes != null then define_volume_mounts(job.volumes),
}],
restartPolicy: 'Never',
volumes: if std.objectHas(job, 'volumes') && job.volumes != null then define_volumes(job.volumes),
},
},
},
},
// ServiceAccount
define_service_account(metadataOrig)::
local metadata = fix_metadata(metadataOrig);
{
apiVersion: 'v1',
kind: 'ServiceAccount',
metadata: metadata {
name: metadata.name + '-serviceaccount',
},
},
// Role
define_role(metadataOrig, rules)::
local metadata = fix_metadata(metadataOrig);
{
apiVersion: 'rbac.authorization.k8s.io/v1',
kind: 'Role',
metadata: metadata {
name: metadata.name + '-role',
},
rules: rules,
},
define_role_v2(metadataOrig, name, rules)::
$.define_role(metadataOrig { name: '%s-%s' % [metadataOrig.name, name] }, rules),
// ClusterRole
define_cluster_role(metadataOrig, rules)::
local metadata = fix_metadata(metadataOrig);
{
apiVersion: 'rbac.authorization.k8s.io/v1',
kind: 'ClusterRole',
metadata: metadata {
name: metadata.name + '-clusterrole',
},
rules: rules,
},
// RoleBinding
define_role_binding(metadataOrig, roleName, subjects)::
local metadata = fix_metadata(metadataOrig);
{
apiVersion: 'rbac.authorization.k8s.io/v1',
kind: 'RoleBinding',
metadata: metadata {
name: metadata.name + '-rolebinding',
},
roleRef: {
apiGroup: 'rbac.authorization.k8s.io',
kind: 'Role',
name: roleName,
},
subjects: subjects,
},
bind_to_role_sa(role, serviceAccount)::
$.define_role_binding(role.metadata, role.metadata.name, [{
kind: 'ServiceAccount',
name: serviceAccount,
namespace: role.metadata.namespace,
}]),
// ClusterRoleBinding
define_cluster_role_binding(metadataOrig, roleName, subjects)::
local metadata = fix_metadata(metadataOrig);
{
apiVersion: 'rbac.authorization.k8s.io/v1',
kind: 'ClusterRoleBinding',
metadata: metadata {
name: metadata.name + '-clusterrolebinding',
},
roleRef: {
apiGroup: 'rbac.authorization.k8s.io',
kind: 'ClusterRole',
name: roleName,
},
subjects: subjects,
},
// PersistentVolumeClaim
define_persistent_volume_claim(metadataOrig, storage, access_mode='ReadWriteOnce')::
local metadata = fix_metadata(metadataOrig);
{
apiVersion: 'v1',
kind: 'PersistentVolumeClaim',
metadata: metadata {
name: metadata.name + '-pvc',
},
spec: {
accessModes: [access_mode],
resources: {
requests: {
storage: storage,
},
},
},
},
// ConfigMap
define_config_map(metadataOrig, data)::
local metadata = fix_metadata(metadataOrig);
{
apiVersion: 'v1',
kind: 'ConfigMap',
metadata: metadata {
name: metadata.name + '-cm',
},
data: data,
},
request_cdb_certs_volumes()::
[
{
name: 'client-certs',
path: '/cockroach-certs',
emptyDir: true,
},
],
request_cdb_certs(user)::
{
name: 'init-certs',
image: ociRegistryDocker + '/cockroachdb/cockroach-k8s-request-cert',
tag: '0.4',
annotations: {
'sidecar.istio.io/inject': 'false',
},
command: [
'/bin/ash',
],
args: [
'-ecx',
'/request-cert -namespace=${POD_NAMESPACE} -certs-dir=/cockroach-certs -type=client -user=' + user + ' -symlink-ca-from=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt && ' +
'chown -R 1000:1000 /cockroach-certs',
],
volumes: $.request_cdb_certs_volumes(),
env: [{
name: 'POD_NAMESPACE',
valueFrom: true,
field: 'metadata.namespace',
}],
},
cdb_sa_roles(metadataOrig)::
local metadata = fix_metadata(metadataOrig);
{
apiVersion: 'v1',
kind: 'List',
items: [
$.define_service_account(metadataOrig),
$.define_role(metadataOrig, [{
apiGroups: [''],
resources: ['secrets'],
verbs: ['create', 'get'],
}]),
$.define_role_binding(metadataOrig, metadata.name + '-role', [{
kind: 'ServiceAccount',
name: metadata.name + '-serviceaccount',
namespace: metadata.namespace,
}]),
$.define_cluster_role(metadataOrig, [{
apiGroups: ['certificates.k8s.io'],
resources: ['certificatesigningrequests'],
verbs: ['create', 'get', 'watch'],
}]),
$.define_cluster_role_binding(metadataOrig, metadata.name + '-clusterrole', [{
kind: 'ServiceAccount',
name: metadata.name + '-serviceaccount',
namespace: metadata.namespace,
}]),
],
},
chown_vm(name, path, id, volumes)::
{
name: 'chown-vm-' + name,
image: 'alpine:3.9.3',
command: [
'chown',
'-R',
'%d:%d' % [id, id],
path,
],
volumes: volumes,
},
istio_labels()::
{
'istio-injection': 'enabled',
},
tag(name, extra=false)::
'%s/%s%s%s%s' % [
std.strReplace(ociRegistry, 'host.docker.internal.local', 'host.docker.internal'),
ociRegistryRepo,
if ociNoNestedSupport then ':' else '/',
name,
if !extra then (if (arch != 'amd64' && !localEnvironment) then '_'+arch else '') else '',
],
tagVersion(name, version)::
'%s%s%s' % [$.tag(name, true), (if ociNoNestedSupport then '-' else ':'), version],
fix_metadata: fix_metadata,
prod: prod,
dev: dev,
version: tag,
}

32
ci/mappings.jsonnet Normal file
View File

@ -0,0 +1,32 @@
local utils = import 'ci/utils.jsonnet';
local sm = import 'ci/service_mappings.jsonnet';
sm.service_mappings + {
get_env_from_svc(svc_name)::
local spl = std.split(svc_name, '-');
spl[std.length(spl) - 1],
get_obj_by_svc(svc_name)::
local env = $.get_env_from_svc(svc_name);
local key = std.strReplace(svc_name, '-%s' % env, '');
if std.objectHas($, key) then $[key] else null,
is_external(svc_name)::
local mapping = $.get_obj_by_svc(svc_name);
if utils.local_image then true else if mapping != null then std.objectHas(mapping, 'external') && mapping.external else false,
should_expose_all(svc_name)::
local mapping = $.get_obj_by_svc(svc_name);
if mapping != null then std.objectHas(mapping, 'expose_all_envs') && mapping.expose_all_envs else false,
get(svc_name, user='')::
local env = $.get_env_from_svc(svc_name);
local mapping = $.get_obj_by_svc(svc_name);
local prefix = if mapping.id == '*' then (if env != 'prod' then mapping.devId else mapping.id) else mapping.id;
local devId = if std.objectHas(mapping, 'devId') then '%s-' % mapping.devId else '';
local prod_def_domain = if utils.local_image then sm.local_domain else (if std.objectHas(mapping, 'domain') then mapping.domain else sm.default_domain);
'%s%s' % [prefix, if env == 'prod' then prod_def_domain else '-%s.internal%s' % [if env == 'dev' && !utils.local_image then '%s%s' % [devId, user] else env, prod_def_domain]],
}

7
ci/ports.jsonnet Normal file
View File

@ -0,0 +1,7 @@
{
https: {
number: 443,
name: 'https',
protocol: 'HTTPS',
}
}

View File

@ -0,0 +1,19 @@
# rename: ci/service_mappings.jsonnet
{
local_domain: '.pdev.rocky.localhost',
default_domain: '.build.rockylinux.org',
service_mappings: {
'peridotserver-http': {
id: 'peridot',
external: true,
},
'yumrepofs-http': {
id: 'yumrepofs',
external: true,
},
'httpbin-http': {
id: 'httpbin',
external: false
}
}
}

View File

@ -0,0 +1,43 @@
# sync-ignore-file: true
{
local_domain: '.pdev.resf.localhost',
default_domain: '.build.resf.org',
service_mappings: {
'peridotserver-http': {
id: 'peridot-api',
external: true,
},
'peridot-frontend-http': {
id: 'peridot',
external: true,
},
'yumrepofs-http': {
id: 'yumrepofs',
external: true,
},
'keykeeper-http': {
id: 'keykeeper',
external: false,
},
'keykeeper-grpc': {
id: 'keykeeper-grpc',
external: false,
},
'httpbin-http': {
id: 'httpbin',
external: true
},
'hydra-public-http': {
id: 'hdr',
external: true
},
'obsidian-http': {
id: 'id-api',
external: true,
},
'obsidian-frontend-http': {
id: 'id',
external: true,
},
}
}

9
ci/temporal.jsonnet Normal file
View File

@ -0,0 +1,9 @@
local utils = import 'ci/utils.jsonnet';
{
hostport: if utils.local_image then 'temporal-frontend.default.svc.cluster.local:7233' else 'workflow-temporal-frontend.workflow.svc.cluster.local:7233',
kube_env(prefix): {
name: '%s_TEMPORAL_HOSTPORT' % prefix,
value: $.hostport,
}
}

10
ci/utils.jsonnet Normal file
View File

@ -0,0 +1,10 @@
local stage = std.extVar('stage');
local ociRegistry = std.extVar('oci_registry');
local ociRegistryDocker = std.extVar('oci_registry_docker');
local localEnvironment = std.extVar('local_environment');
local localImage = if localEnvironment == "1" then true else false;
{
local_image: localImage,
docker_hub_image(name): "%s/%s" % [ociRegistryDocker, name],
}

0
common/BUILD Normal file
View File

View File

@ -0,0 +1,26 @@
load("@raw_ts_library//:index.bzl", "raw_ts_library")
raw_ts_library(
name = "frontend_server",
srcs = [
"index.mjs",
"upstream.mjs",
],
module_name = "common/frontend_server",
visibility = ["//visibility:public"],
deps = [
"@npm//body-parser",
"@npm//connect-history-api-fallback",
"@npm//cookie-parser",
"@npm//evil-dns",
"@npm//express",
"@npm//express-openid-connect",
"@npm//hbs",
"@npm//helmet",
"@npm//http-proxy-middleware",
"@npm//webpack",
"@npm//webpack-dev-middleware",
"@npm//webpack-hot-middleware",
"@npm//webpack-mild-compile",
],
)

View File

@ -0,0 +1,305 @@
/*
* Copyright (c) All respective contributors to the Peridot Project. All rights reserved.
* Copyright (c) 2021-2022 Rocky Enterprise Software Foundation, Inc. All rights reserved.
* Copyright (c) 2021-2022 Ctrl IQ, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
import express from 'express';
import httpProxyMiddleware from 'http-proxy-middleware';
import bodyParser from 'body-parser';
import cookieParser from 'cookie-parser';
import helmet from 'helmet';
import webpack from 'webpack';
import webpackDevMiddleware from 'webpack-dev-middleware';
import webpackHotMiddleware from 'webpack-hot-middleware';
import webpackMildCompile from 'webpack-mild-compile';
import expressOidc from 'express-openid-connect';
import history from 'connect-history-api-fallback';
import hbs from 'hbs';
import evilDns from 'evil-dns';
import fs from 'fs';
import dns from 'dns';
const { createProxyMiddleware } = httpProxyMiddleware;
const { auth } = expressOidc;
export default async function(opts) {
// Create a new app for health checks.
const appZ = express();
appZ.get('/_/healthz', ((req, res) => {
res.end();
}));
const app = express();
app.use(function(req, res, next) {
// Including byc-internal-req: 1 should return the Z page
if (req.header('byc-internal-req') === 'yes') {
appZ(req, res, next);
} else {
next();
}
});
const prod = process.env.NODE_ENV === 'production';
const port = prod ? (process.env.PORT || 8086) : opts.port;
opts.secret = process.env.BYC_SECRET;
// If we're in prod, then a secret has to be present
if (prod && (!opts.secret || opts.secret.length < 32)) {
throw 'secret has to be at least 32 characters';
}
// Add authentication if not disabled
if (!opts.disableAuth) {
console.log(`Using issuer: ${opts.issuerBaseURL}`);
console.log(`Using clientID: ${opts.clientID}`);
console.log(`Using baseURL: ${opts.baseURL}`);
if (opts.issuerBaseURL.endsWith('.localhost') || opts.issuerBaseURL.endsWith('.localhost/')) {
const kong = 'kong-proxy.kong.svc.cluster.local'
const urlObject = new URL(opts.issuerBaseURL);
console.warn(`Forcing ${urlObject.hostname} to resolve to ${kong}`);
const lookup = async () => {
return new Promise((resolve, reject) => {
// noinspection HttpUrlsUsage
dns.lookup(kong, { family: 4 }, (err, address, family) => {
if(err) reject(err);
resolve(address);
});
});
};
const internalServiceResolve = await lookup();
evilDns.add(urlObject.hostname, internalServiceResolve);
// Disable TLS verification for development
process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = 0
}
const config = {
authRequired: (process.env['DISABLE_AUTH_ENFORCE'] && process.env['DISABLE_AUTH_ENFORCE'] === 'false') || !!!opts.disableAuthEnforce,
// Disable telemetry
enableTelemetry: false,
// Use dev secret is none is present (Prod requires a secret so not a security issue)
secret: opts.secret || 'dev-secret-123',
// Add BaseURL for callback purposes. This has to be specified in the initial server call
// The FRONTEND_URL environment variable can override this value in prod.
baseURL: opts.baseURL,
// The specific application should supply a dev client ID while prod IDs should be set as an env variable
clientID: opts.clientID,
// The specific application should supply a dev secret while prod secrets should be set as an env variable
clientSecret: opts.clientSecret,
// We're currently only using the Rocky issuer
issuerBaseURL: opts.issuerBaseURL,
idpLogout: true,
authorizationParams: {
response_type: 'code',
scope: 'openid profile email offline_access'
},
session: {
rolling: true,
rollingDuration: 86400,
absoluteDuration: 86400 * 7
},
routes: {
callback: '/oauth2/callback',
logout: '/oauth2/logout',
login: '/oauth2/login'
}
};
// If we have a authentication prefix, only force redirect on paths with that prefix
// Remember, authentication done here is only for simplicity purposes.
// The authentication token is then passed on to the API.
// Bypassing auth here doesn't accomplish anything.
app.use((req, res, next) => {
try {
auth(config)(req, res, next);
} catch (err) {
next(err);
}
});
}
// Currently in dev, webpack is handling all file serving
// This is just a placeholder
let distDir = process.cwd() + '/dist';
if (prod) {
// Enable security hardening in prod
app.use(helmet({
contentSecurityPolicy: false
}));
// Prod expects a certain container structure for all apps
// Packaging this application with the web base should do
// all this for you
const dirs = fs.readdirSync('/home/app/bundle');
distDir = `/home/app/bundle/${dirs[0]}`;
}
app.set('views', distDir);
app.use(cookieParser());
app.set('view engine', 'hbs');
// Use the handlebar engine
app.engine('hbs', hbs.__express);
app.use(express.static(distDir));
if (opts.apis) {
Object.keys(opts.apis).forEach(x => {
app.use(x, async (req, res, next) => {
let authorization = '';
// If we have an authenticated user, send the token with the request
if (req.oidc && req.oidc.accessToken) {
let { access_token, isExpired, refresh } = req.oidc.accessToken;
if (isExpired()) {
try {
({ access_token } = await refresh());
} catch (err) {
res.oidc.logout({ returnTo: '/' });
return next('User has to re-authenticate');
}
}
authorization = `Bearer ${access_token}`;
if (!prod) {
console.log(`Using id token: ${req.oidc.idToken}`);
console.log(`Using access token: ${access_token}`);
}
}
const rewrite = {};
rewrite[`^${x}`] = '';
// Make it possible to override api url using an env variable.
// Example: /api can be set with URL_API
// Example 2: /manage/api can be set with URL_MANAGE_API
const prodEnvName = `URL_${x.substr(1).replace('/', '_').toUpperCase()}`;
const apiUrl = prod ? (process.env[prodEnvName] || opts.apis[x].prodApiUrl) : opts.apis[x].devApiUrl;
createProxyMiddleware({
target: apiUrl,
changeOrigin: true,
headers: {
host: apiUrl,
authorization
},
pathRewrite: rewrite
})(req, res);
});
});
}
// Template parameters for values in initial state
const templateParams = (req) => {
// If auth is disabled, then either return an empty list
// or run the templateFunc WITHOUT a user.
// It's important that apps do not use `user` without validation
if (opts.disableAuth || !req.oidc) {
if (opts.templateFunc) {
return opts.templateFunc();
}
return {};
}
const { user } = req.oidc;
if (!user) {
return {};
}
if (opts.templateFunc) {
return opts.templateFunc(user);
}
// Return default values
const { email, name, picture } = user;
return {
email,
name,
picture
};
};
if (prod) {
app.get('/*', (req, res) => {
// Prod doesn't do hacky shit with the webpack compiler so just add the params
// to the locals
res.locals = templateParams(req);
res.render('index');
});
} else {
// Here comes the hack train
if (!opts.webpackConfig && opts.webpackPath) {
opts.webpackConfig = await import(opts.webpackPath);
}
// Create a live-reloading dev instance of the app with the given webpack config
const compiler = webpack(opts.webpackConfig);
webpackMildCompile(compiler);
const wdm = webpackDevMiddleware(compiler, {
publicPath: opts.webpackConfig.output.publicPath,
});
app.use(history());
app.use((req, res, next) => {
// Here we cache the old send function to re-use after we run the HTML through handlebars
const oldSend = res.send;
res.send = data => {
let newData;
// Check if the request returned a HTML page
// For SPAs, the only HTML page is the index page
if (res.get('content-type').indexOf('text/html') !== -1) {
// Run through handlebars compiler with our template parameters
newData = hbs.handlebars.compile(data.toString())(templateParams(req));
} else {
// No new data, just return old data
newData = data;
}
// Re-replace res.send with the old res.send
res.send = oldSend;
// Run the old res.send with the new data
return res.send(newData);
};
next();
});
// Enable hot reload
app.use(wdm);
app.use(webpackHotMiddleware(compiler));
}
// Enable JSON bodies. We're forwarding this to the API
app.use(bodyParser.json());
console.log(`view app on ${opts.baseURL}`);
app.listen(port);
}

View File

@ -0,0 +1,64 @@
/*
* Copyright (c) All respective contributors to the Peridot Project. All rights reserved.
* Copyright (c) 2021-2022 Rocky Enterprise Software Foundation, Inc. All rights reserved.
* Copyright (c) 2021-2022 Ctrl IQ, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
import os from 'os';
export function svcName(svc, protocol) {
let env = process.env['BYC_ENV'];
return `${svc}-${protocol}-${env}-service`;
}
export function svcNameHttp(svc) {
return svcName(svc, 'http');
}
export function endpoint(generatedServiceName, ns, port) {
return `${generatedServiceName}.${ns}.svc.cluster.local${port}`;
}
export function endpointHttp(generatedServiceName, ns, port = '') {
// noinspection HttpUrlsUsage
return `http://${endpoint(generatedServiceName, ns, port)}`;
}
export function NS(ns) {
const env = process.env['BYC_ENV'];
if (!env || env === 'dev') {
const bycNs = process.env['BYC_NS'];
if (!bycNs) {
return `${os.userInfo().username}-dev`;
}
return bycNs;
}
return ns;
}

19
common/mui/BUILD Normal file
View File

@ -0,0 +1,19 @@
load("@raw_ts_library//:index.bzl", "raw_ts_library")
package(default_visibility = ["//visibility:public"])
raw_ts_library(
name = "mui",
srcs = glob([
"*.ts",
"*.tsx",
"*.less",
]),
module_name = "common/mui",
deps = [
"@npm//@emotion/react",
"@npm//@emotion/styled",
"@npm//@mui/material",
"@npm//@mui/styles",
],
)

86
common/mui/DenseList.tsx Normal file
View File

@ -0,0 +1,86 @@
/*
* Copyright (c) All respective contributors to the Peridot Project. All rights reserved.
* Copyright (c) 2021-2022 Rocky Enterprise Software Foundation, Inc. All rights reserved.
* Copyright (c) 2021-2022 Ctrl IQ, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
import React from 'react';
import List from '@mui/material/List';
import ListItemText from '@mui/material/ListItemText';
export interface DenseListEntry {
key?: string;
value?: string;
entries?: DenseListEntry[];
}
export interface DenseListProps {
entries: DenseListEntry[];
}
const listEntry = (
nestLevel: number,
key?: string,
value?: string,
entries?: DenseListEntry[]
): React.ReactNode => {
return (
<>
<div className="flex justify-between items-center">
{key && (
<ListItemText
classes={{ primary: 'text-sm font-bold' }}
sx={{ pl: 6 * nestLevel }}
primary={key}
/>
)}
{value && (
<ListItemText
classes={{ secondary: 'text-sm' }}
sx={key ? undefined : { pl: 6 * nestLevel }}
secondary={value}
/>
)}
</div>
{entries?.map((entry) =>
listEntry(nestLevel + 1, entry.key, entry.value, entry.entries)
)}
</>
);
};
export const DenseList = (props: DenseListProps) => {
return (
<List dense className="w-96 divide-y">
{props.entries.map((entry) =>
listEntry(0, entry.key, entry.value, entry.entries)
)}
</List>
);
};

85
common/mui/Header.tsx Normal file
View File

@ -0,0 +1,85 @@
/*
* Copyright (c) All respective contributors to the Peridot Project. All rights reserved.
* Copyright (c) 2021-2022 Rocky Enterprise Software Foundation, Inc. All rights reserved.
* Copyright (c) 2021-2022 Ctrl IQ, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
import * as React from 'react';
import AppBar from '@mui/material/AppBar';
import Avatar from '@mui/material/Avatar';
import Button from '@mui/material/Button';
import Grid from '@mui/material/Grid';
import HelpIcon from '@mui/icons-material/Help';
import IconButton from '@mui/material/IconButton';
import Link from '@mui/material/Link';
import MenuIcon from '@mui/icons-material/Menu';
import NotificationsIcon from '@mui/icons-material/Notifications';
import Tab from '@mui/material/Tab';
import Tabs from '@mui/material/Tabs';
import Toolbar from '@mui/material/Toolbar';
import Tooltip from '@mui/material/Tooltip';
import Typography from '@mui/material/Typography';
const lightColor = 'rgba(255, 255, 255, 0.7)';
export interface HeaderProps {
title: string;
tabs?: React.ReactNode;
toolbarChildren?: React.ReactNode;
}
export const Header = (props: HeaderProps) => {
return (
<>
<AppBar color="primary" position="static" elevation={0}>
<Toolbar />
</AppBar>
<AppBar
component="div"
color="primary"
position="sticky"
elevation={0}
>
<Toolbar>
<Grid container alignItems="center" spacing={1}>
<Grid item xs>
<Typography color="inherit" variant="h5" component="h1">
{props.title}
</Typography>
</Grid>
{props.toolbarChildren}
</Grid>
</Toolbar>
</AppBar>
<AppBar component="div" position="static" elevation={0} sx={{ zIndex: 0 }}>
{props.tabs}
</AppBar>
</>
);
}

241
common/mui/NavbarDrawer.tsx Normal file
View File

@ -0,0 +1,241 @@
/*
* Copyright (c) All respective contributors to the Peridot Project. All rights reserved.
* Copyright (c) 2021-2022 Rocky Enterprise Software Foundation, Inc. All rights reserved.
* Copyright (c) 2021-2022 Ctrl IQ, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
import React from 'react';
import { match, useLocation } from 'react-router';
import * as H from 'history';
import AppBar from '@mui/material/AppBar';
import Drawer from '@mui/material/Drawer';
import IconButton from '@mui/material/IconButton';
import Button from '@mui/material/Button';
import MenuIcon from '@mui/icons-material/Menu';
import PersonIcon from '@mui/icons-material/Person';
import LoginIcon from '@mui/icons-material/Login';
import LogoutIcon from '@mui/icons-material/Logout';
import ChevronLeftIcon from '@mui/icons-material/ChevronLeft';
import { PeridotLogo } from 'common/ui/PeridotLogo';
import Toolbar from '@mui/material/Toolbar';
import Divider from '@mui/material/Divider';
import { NavLink, Link, NavLinkProps, useRouteMatch } from 'react-router-dom';
import ListItem from '@mui/material/ListItem/ListItem';
import ListItemText from '@mui/material/ListItemText';
import { peridotTheme, primaryColor } from './theme';
import FormControl from '@mui/material/FormControl';
import InputLabel from '@mui/material/InputLabel';
import Select from '@mui/material/Select';
import MenuItem from '@mui/material/MenuItem';
import ListItemIcon from '@mui/material/ListItemIcon';
import List from '@mui/material/List';
import Box from '@mui/material/Box';
import ListItemButton from '@mui/material/ListItemButton';
import useMediaQuery from '@mui/material/useMediaQuery';
export interface NavbarLink extends Pick<NavLinkProps, 'isActive'> {
text: string;
href: string;
real?: boolean;
exact?: boolean;
icon?(classes: string): React.ReactNode;
}
export interface NavbarCategories {
title?: string;
links: (NavbarLink | undefined)[];
}
export interface NavbarDrawerProps {
mainLinks?: NavbarCategories[];
afterLogoNode?: () => React.ReactNode;
logo(classes: string): React.ReactNode;
}
interface LinkRealWrapperProps extends Pick<NavLinkProps, 'isActive'> {
to: string;
children: React.ReactNode;
real?: boolean;
exact?: boolean;
onClick?(): void;
}
const LinkRealWrapper = (props: LinkRealWrapperProps) => {
const linkClasses = 'hover:bg-gray-100 focus:bg-gray-100';
return props.real ? (
<a className={linkClasses} href={props.to} onClick={props.onClick}>
{props.children}
</a>
) : (
<NavLink
className={linkClasses}
activeClassName="text-peridot-primary"
to={props.to}
isActive={props.isActive}
exact={props.exact}
onClick={props.onClick}
>
{props.children}
</NavLink>
);
};
const itemNoHover = {
py: '2px',
px: 3,
color: 'rgba(255, 255, 255, 0.7)',
};
const item = Object.assign({}, itemNoHover, {
'&:hover, &:focus': {
bgcolor: 'rgba(255, 255, 255, 0.08)',
},
});
const itemCategory = {
boxShadow: '0 -1px 0 rgb(255,255,255,0.1) inset',
py: 1.5,
px: 3,
};
export const NavbarDrawer = (props: NavbarDrawerProps) => {
const location = useLocation();
const [drawerOpen, setDrawerOpen] = React.useState(false);
const isSmUp = useMediaQuery(peridotTheme.breakpoints.up('sm'));
const toggleDrawer = () => {
setDrawerOpen(!drawerOpen);
};
return (
<>
<Box component="nav" sx={{ width: { sm: 256 }, flexShrink: { sm: 0 } }}>
<Drawer
variant={isSmUp ? 'permanent' : 'temporary'}
open={isSmUp ? true : drawerOpen}
onClose={isSmUp ? undefined : toggleDrawer}
PaperProps={{ style: { width: 256 } }}
sx={isSmUp ? { display: { sm: 'block', xs: 'none' } } : null}
>
<List disablePadding>
<ListItem
sx={{
...itemNoHover,
...itemCategory,
fontSize: 22,
color: '#fff',
}}
>
{props.logo('h-8')}
</ListItem>
{window.state.email ? (
<ListItem sx={{ ...itemNoHover, ...itemCategory }}>
<ListItemIcon>
<PersonIcon />
</ListItemIcon>
<ListItemText className="text-ellipsis overflow-hidden">
{window.state.name && window.state.name.length > 0
? window.state.name
: window.state.email}
</ListItemText>
<a href="/oauth2/logout">
<LogoutIcon fontSize="small" />
</a>
</ListItem>
) : (
<ListItem sx={{ ...itemNoHover, ...itemCategory }}>
<a className="flex items-center" href="/oauth2/login">
<ListItemIcon>
<LoginIcon />
</ListItemIcon>
<ListItemText>Login</ListItemText>
</a>
</ListItem>
)}
{props.afterLogoNode && (
<ListItem sx={{ ...itemNoHover, ...itemCategory }}>
<ListItemText>{props.afterLogoNode()}</ListItemText>
</ListItem>
)}
{props.mainLinks?.map((category) => (
<Box key={category.title || 'empty'} sx={{ bgcolor: '#101F33' }}>
{category.title ? (
<ListItem sx={{ py: 2, px: 3 }}>
<ListItemText sx={{ color: '#fff' }}>
{category.title}
</ListItemText>
</ListItem>
) : (
<div className="pt-4" />
)}
{category.links.map((link: NavbarLink | undefined) => {
if (!link) {
return null;
}
let match = useRouteMatch({
path: link.href,
exact: link.exact,
});
if (link.isActive && !link.isActive(match, location)) {
match = null;
}
return (
<LinkRealWrapper
key={link.href}
to={link.href}
real={link.real}
isActive={link.isActive}
exact={link.exact}
>
<ListItem disablePadding>
<ListItemButton selected={!!match} sx={item}>
{link.icon && (
<ListItemIcon>{link.icon('')}</ListItemIcon>
)}
<ListItemText primary={link.text} />
</ListItemButton>
</ListItem>
</LinkRealWrapper>
);
})}
<Divider sx={{ mt: 2 }} />
</Box>
))}
</List>
</Drawer>
</Box>
</>
);
};

View File

@ -0,0 +1,48 @@
/*
* Copyright (c) All respective contributors to the Peridot Project. All rights reserved.
* Copyright (c) 2021-2022 Rocky Enterprise Software Foundation, Inc. All rights reserved.
* Copyright (c) 2021-2022 Ctrl IQ, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
import React from 'react';
import Toolbar from '@mui/material/Toolbar';
export interface ToolbarHeaderProps {
children: React.ReactNode;
}
export const ToolbarHeader = (props: ToolbarHeaderProps) => {
return (
<>
<Toolbar className="py-3 bg-white" variant="dense">
{props.children}
</Toolbar>
</>
);
};

189
common/mui/theme.tsx Normal file
View File

@ -0,0 +1,189 @@
/*
* Copyright (c) All respective contributors to the Peridot Project. All rights reserved.
* Copyright (c) 2021-2022 Rocky Enterprise Software Foundation, Inc. All rights reserved.
* Copyright (c) 2021-2022 Ctrl IQ, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
import React from 'react';
import { ThemeOptions, createTheme } from '@mui/material/styles';
import ThemeProvider, {
ThemeProviderProps,
} from '@mui/material/styles/ThemeProvider';
export const primaryColor = '#1976d2';
export const secondaryColor = '#19b2d1';
export const peridotThemeOptions: ThemeOptions = {
palette: {
primary: {
light: '#63ccff',
main: '#009be5',
dark: '#006db3',
},
},
typography: {
fontFamily: 'Inter',
h5: {
fontWeight: 500,
fontSize: 26,
letterSpacing: 0.5,
},
},
shape: {
borderRadius: 8,
},
mixins: {
toolbar: {
minHeight: 48,
},
},
};
export let peridotTheme = createTheme(peridotThemeOptions);
peridotTheme = {
...peridotTheme,
components: {
MuiDrawer: {
styleOverrides: {
paper: {
backgroundColor: '#081627',
},
},
},
MuiButton: {
styleOverrides: {
root: {
textTransform: 'none',
},
contained: {
boxShadow: 'none',
'&:active': {
boxShadow: 'none',
},
},
},
},
MuiTabs: {
styleOverrides: {
root: {
marginLeft: peridotTheme.spacing(1),
},
indicator: {
height: 3,
borderTopLeftRadius: 3,
borderTopRightRadius: 3,
},
},
},
MuiTab: {
styleOverrides: {
root: {
textTransform: 'none',
minWidth: 0,
padding: 0,
[peridotTheme.breakpoints.up('md')]: {
padding: '0 10px',
minWidth: 0,
},
},
},
},
MuiIconButton: {
styleOverrides: {
root: {
padding: peridotTheme.spacing(1),
},
},
},
MuiTooltip: {
styleOverrides: {
tooltip: {
borderRadius: 4,
},
},
},
MuiDivider: {
styleOverrides: {
root: {
backgroundColor: 'rgb(255,255,255,0.15)',
},
},
},
MuiListItemButton: {
styleOverrides: {
root: {
'&.Mui-selected': {
color: '#4fc3f7',
},
},
},
},
MuiListItemText: {
styleOverrides: {
primary: {
fontSize: 14,
fontWeight: peridotTheme.typography.fontWeightMedium,
},
},
},
MuiListItemIcon: {
styleOverrides: {
root: {
color: 'inherit',
minWidth: 'auto',
marginRight: peridotTheme.spacing(2),
'& svg': {
fontSize: 20,
},
},
},
},
MuiAvatar: {
styleOverrides: {
root: {
width: 32,
height: 32,
},
},
},
},
};
export interface PeridotThemeProviderProps
extends Omit<ThemeProviderProps, 'theme'> {}
export const PeridotThemeProvider = (props: PeridotThemeProviderProps) => {
const { children, ...restProps } = props;
return (
<ThemeProvider theme={peridotTheme} {...restProps}>
{props.children}
</ThemeProvider>
);
};

20
common/ui/BUILD Normal file
View File

@ -0,0 +1,20 @@
load("@raw_ts_library//:index.bzl", "raw_ts_library")
package(default_visibility = ["//visibility:public"])
raw_ts_library(
name = "ui",
srcs = glob([
"*.ts",
"*.tsx",
"*.less",
]),
module_name = "common/ui",
deps = [
"@npm//ansi-regex",
"@npm//classnames",
"@npm//path-to-regexp",
"@npm//popper.js",
"@npm//strip-ansi",
],
)

54
common/ui/PeridotLink.tsx Normal file
View File

@ -0,0 +1,54 @@
/*
* Copyright (c) All respective contributors to the Peridot Project. All rights reserved.
* Copyright (c) 2021-2022 Rocky Enterprise Software Foundation, Inc. All rights reserved.
* Copyright (c) 2021-2022 Ctrl IQ, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
import React from 'react';
import classnames from 'classnames';
import { LinkProps, Link } from 'react-router-dom';
export interface PeridotLinkProps extends LinkProps {
real?: boolean;
}
export const PeridotLink = (props: PeridotLinkProps) => {
const { real, className, ...rest } = props;
const cnames = classnames(
className,
'no-underline text-peridot-primary visited:text-purple-500'
);
return real ? (
<a href={props.to.toString()} className={cnames} {...rest} />
) : (
<Link className={cnames} {...rest} />
);
};

54
common/ui/PeridotLogo.tsx Normal file

File diff suppressed because one or more lines are too long

62
common/ui/RockyLogo.tsx Normal file
View File

@ -0,0 +1,62 @@
/*
* Copyright (c) All respective contributors to the Peridot Project. All rights reserved.
* Copyright (c) 2021-2022 Rocky Enterprise Software Foundation, Inc. All rights reserved.
* Copyright (c) 2021-2022 Ctrl IQ, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
import React from 'react';
import classnames from 'classnames';
export interface RockyLogoProps {
className?: string;
}
export const RockyLogo = (props: RockyLogoProps) => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="1104"
height="256"
fill="none"
className={classnames('mt-2 h-8 w-auto sm:h-10', props.className)}
viewBox="0 0 1104 256"
>
<path
fill="#10B981"
fillRule="evenodd"
d="M186.658 128.658C190.119 118.746 192 108.093 192 97c0-53.02-42.981-96-96-96C42.98 1 0 43.98 0 97c0 26.234 10.523 50.011 27.578 67.338l97.38-97.38L149 91l37.658 37.658zm-17.536 30.547l-44.164-44.163-69.16 69.16C68.027 189.849 81.645 193 96 193c29.288 0 55.514-13.116 73.122-33.795z"
clipRule="evenodd"
/>
<path
d="M251.072 147V46.2h49.248c5.088 0 9.744.768 13.968 2.304 4.32 1.536 8.016 3.696 11.088 6.48 3.072 2.688 5.472 5.952 7.2 9.792 1.728 3.84 2.592 8.064 2.592 12.672 0 6.336-1.824 12-5.472 16.992-3.552 4.992-8.304 8.688-14.256 11.088L337.76 147h-23.328l-19.728-38.592h-22.752V147h-20.88zm47.376-82.8h-26.496v27.072h26.496c4.704 0 8.448-1.248 11.232-3.744 2.88-2.496 4.32-5.76 4.32-9.792s-1.44-7.296-4.32-9.792c-2.784-2.496-6.528-3.744-11.232-3.744zm41.247 45.36c0-5.472 1.008-10.56 3.024-15.264 2.112-4.8 4.944-8.928 8.496-12.384 3.648-3.552 7.92-6.336 12.816-8.352 4.896-2.016 10.128-3.024 15.696-3.024s10.8 1.008 15.696 3.024c4.896 2.016 9.12 4.8 12.672 8.352 3.648 3.456 6.48 7.584 8.496 12.384 2.112 4.704 3.168 9.792 3.168 15.264 0 5.472-1.056 10.608-3.168 15.408-2.016 4.704-4.848 8.784-8.496 12.24-3.552 3.456-7.776 6.192-12.672 8.208-4.896 2.016-10.128 3.024-15.696 3.024s-10.8-1.008-15.696-3.024c-4.896-2.016-9.168-4.752-12.816-8.208-3.552-3.456-6.384-7.536-8.496-12.24-2.016-4.8-3.024-9.936-3.024-15.408zm40.032 21.744c5.76 0 10.656-2.112 14.688-6.336s6.048-9.36 6.048-15.408c0-6.144-2.016-11.328-6.048-15.552s-8.928-6.336-14.688-6.336-10.656 2.112-14.688 6.336-6.048 9.408-6.048 15.552c0 6.048 2.016 11.184 6.048 15.408s8.928 6.336 14.688 6.336zm89.441-.144c3.36 0 6.48-.672 9.36-2.016 2.976-1.344 5.808-3.456 8.496-6.336l11.808 12.24c-3.84 4.224-8.448 7.536-13.824 9.936-5.376 2.304-10.944 3.456-16.704 3.456-5.472 0-10.656-1.008-15.552-3.024-4.8-2.016-8.976-4.752-12.528-8.208-3.456-3.456-6.192-7.536-8.208-12.24-2.016-4.8-3.024-9.936-3.024-15.408 0-5.472 1.008-10.56 3.024-15.264 2.016-4.8 4.752-8.928 8.208-12.384 3.552-3.552 7.728-6.336 12.528-8.352 4.896-2.016 10.08-3.024 15.552-3.024 5.952 0 11.664 1.2 17.136 3.6 5.472 2.304 10.128 5.568 13.968 9.792l-12.096 12.816c-2.688-2.976-5.568-5.232-8.64-6.768-3.072-1.536-6.384-2.304-9.936-2.304-5.664 0-10.464 2.112-14.4 6.336-3.84 4.224-5.76 9.408-5.76 15.552s1.968 11.28 5.904 15.408c4.032 4.128 8.928 6.192 14.688 6.192zM509.089 147V46.2l19.728-4.32v61.776l32.4-31.68h22.32l-35.136 34.416L585.697 147h-25.2l-31.68-34.272V147h-19.728zm103.554 3.456l1.152-2.736-29.233-75.744h21.745l18.576 51.12 21.312-51.12h21.312l-34.56 80.928c-3.84 9.024-8.304 15.456-13.392 19.296-5.088 3.84-11.712 5.76-19.872 5.76-1.728 0-3.408-.096-5.04-.288-1.536-.096-2.784-.288-3.744-.576v-16.992c.96.192 1.968.336 3.024.432 1.056.096 2.352.144 3.888.144 3.552 0 6.528-.864 8.928-2.592 2.496-1.728 4.464-4.272 5.904-7.632zM706.744 147V46.2h11.088v90.864h60.048V147h-71.136zm90.219-85.968c-1.92 0-3.6-.72-5.04-2.16-1.44-1.44-2.16-3.12-2.16-5.04 0-2.016.72-3.696 2.16-5.04 1.44-1.44 3.12-2.16 5.04-2.16 2.016 0 3.696.72 5.04 2.16 1.44 1.344 2.16 3.024 2.16 5.04 0 1.92-.72 3.6-2.16 5.04-1.344 1.44-3.024 2.16-5.04 2.16zm5.328 13.824V147h-10.656V74.856h10.656zM820.463 147V74.856h10.656v8.496c2.784-3.264 6.096-5.712 9.936-7.344 3.84-1.728 8.112-2.592 12.816-2.592 8.16 0 14.832 2.592 20.016 7.776 5.184 5.184 7.776 11.904 7.776 20.16V147h-10.512v-43.488c0-6.336-1.824-11.376-5.472-15.12-3.648-3.744-8.544-5.616-14.688-5.616-4.32 0-8.208.96-11.664 2.88-3.36 1.92-6.096 4.656-8.208 8.208V147h-10.656zm88.552-72.144v43.488c0 6.336 1.824 11.376 5.472 15.12 3.648 3.744 8.544 5.616 14.688 5.616 4.32 0 8.16-.96 11.52-2.88 3.456-2.016 6.24-4.8 8.352-8.352V74.856h10.656V147h-10.656v-8.352c-2.784 3.264-6.096 5.712-9.936 7.344-3.744 1.632-7.968 2.448-12.672 2.448-8.256 0-14.976-2.592-20.16-7.776-5.184-5.184-7.776-11.904-7.776-20.16V74.856h10.512zM969.47 147l28.368-37.152-26.928-34.992h12.672l20.448 27.072 20.45-27.072h12.24l-26.64 34.848L1038.59 147h-12.67l-22.03-29.376L981.566 147H969.47zM1048 70.624V54.976h-5.18v-3.024h5.18v-6.096l3.5-.912v7.008h7.25v3.024h-7.25v14.736c0 1.28.29 2.208.87 2.784.57.544 1.52.816 2.83.816.67 0 1.26-.048 1.78-.144a9.924 9.924 0 001.72-.48v3.12c-.6.224-1.29.384-2.06.48-.74.096-1.46.144-2.16.144-2.08 0-3.68-.496-4.8-1.488-1.12-.992-1.68-2.432-1.68-4.32zM1062.56 76V51.952h3.55v2.64c.89-1.024 1.93-1.792 3.12-2.304 1.18-.544 2.49-.816 3.93-.816 1.67 0 3.16.4 4.47 1.2a8.08 8.08 0 013.12 3.168c.99-1.472 2.17-2.56 3.55-3.264 1.41-.736 2.98-1.104 4.7-1.104 2.6 0 4.71.864 6.34 2.592 1.66 1.728 2.5 3.968 2.5 6.72V76h-3.51V61.504c0-2.112-.56-3.792-1.68-5.04-1.12-1.248-2.64-1.872-4.56-1.872-1.31 0-2.51.336-3.6 1.008-1.09.672-2.01 1.648-2.78 2.928.06.352.11.72.14 1.104.07.352.1.736.1 1.152V76h-3.51V61.504c0-2.112-.56-3.792-1.68-5.04-1.12-1.248-2.62-1.872-4.51-1.872-1.28 0-2.45.304-3.5.912-1.03.576-1.91 1.44-2.64 2.592V76h-3.55z"
className="logo-text"
/>
</svg>
);
};

View File

@ -0,0 +1,54 @@
/*
* Copyright (c) All respective contributors to the Peridot Project. All rights reserved.
* Copyright (c) 2021-2022 Rocky Enterprise Software Foundation, Inc. All rights reserved.
* Copyright (c) 2021-2022 Ctrl IQ, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
import React, { Suspense } from 'react';
import { loadingElement } from './remote';
export type ReactPromise =
| Promise<React.ComponentClass>
| Promise<React.FunctionComponent>;
export const generateSuspensedComponent = (
importComponent: () => Promise<{ default: any }>,
padding?: boolean
) => {
const Content = React.lazy(importComponent);
// tslint:disable-next-line
return (props: any) => (
<Suspense
fallback={<div className={padding ? 'p-8' : ''}>{loadingElement}</div>}
>
<Content {...props} />
</Suspense>
);
};

43
common/ui/index.d.ts vendored Normal file
View File

@ -0,0 +1,43 @@
/*
* Copyright (c) All respective contributors to the Peridot Project. All rights reserved.
* Copyright (c) 2021-2022 Rocky Enterprise Software Foundation, Inc. All rights reserved.
* Copyright (c) 2021-2022 Ctrl IQ, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
export {};
interface State {
email: string;
name: string;
picture: string;
}
declare global {
interface Window {
state: State;
}
}

111
common/ui/remote.tsx Normal file
View File

@ -0,0 +1,111 @@
/*
* Copyright (c) All respective contributors to the Peridot Project. All rights reserved.
* Copyright (c) 2021-2022 Rocky Enterprise Software Foundation, Inc. All rights reserved.
* Copyright (c) 2021-2022 Ctrl IQ, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
import Alert from '@mui/material/Alert';
import { H1 } from 'dotui/H1';
import { H2 } from 'dotui/H2';
import { H4 } from 'dotui/H4';
import { H5 } from 'dotui/H5';
import { PageWrapper } from 'dotui/PageWrapper';
import React from 'react';
import { reqap } from './reqap';
import { RemoteState, AccessDeniedError } from './types';
export var loadingElement: React.ReactElement = <div>Loading...</div>;
export const setLoadingElement = (elem: React.ReactElement) => {
loadingElement = elem;
};
export function fetchRemoteResource<T, X>(
fetchFunction: () => Promise<T>,
setFunction: (val: RemoteState<T>) => void,
disableEffect: boolean = false,
effectArray: any[] = []
) {
const remoteMethod = async () => {
const [err, res] = await reqap(() => fetchFunction());
if (err) {
if (err.status === 403) {
setFunction('access_denied');
} else {
setFunction(null);
}
}
if (res) {
setFunction(res);
}
};
if (disableEffect) {
remoteMethod().then();
} else {
React.useEffect(() => {
remoteMethod().then();
}, effectArray);
}
}
export function suspenseRemoteResource<T>(
state: RemoteState<T>,
render: (res: T) => React.ReactNode,
wrap: ((elem: React.ReactNode) => React.ReactNode) | undefined = undefined
): React.ReactNode {
const wrapHelper = (elem: React.ReactNode) => {
if (wrap) {
return wrap(elem);
}
return elem;
};
if (state === undefined) {
return wrapHelper(loadingElement);
} else if (state === 'access_denied') {
return wrapHelper(
<Alert severity="error">
Access to resource has been denied. Contact an administrator if you
think this is a mistake
</Alert>
);
} else if (state === null) {
return wrapHelper(
<div className="flex items-center justify-center flex-col mt-4">
<H2>Could not fetch remote resource</H2>
<H4>Please try again later</H4>
</div>
);
} else {
return render(state);
}
}

67
common/ui/reqap.ts Normal file
View File

@ -0,0 +1,67 @@
/*
* Copyright (c) All respective contributors to the Peridot Project. All rights reserved.
* Copyright (c) 2021-2022 Rocky Enterprise Software Foundation, Inc. All rights reserved.
* Copyright (c) 2021-2022 Ctrl IQ, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
import to from 'await-to-js';
export interface GrpcError {
code: number;
error: string;
message: string;
status: number;
}
export function reqap<T, U = GrpcError>(
run: () => Promise<void | T>
): Promise<[U | null, void | T | undefined]> {
return to(
run().catch((e) => {
if (!e.status && e.type !== 'opaqueredirect') {
return;
}
const invalidStatuses = [302, 401];
if (invalidStatuses.includes(e.status) || e.type === 'opaqueredirect') {
window.location.reload();
return;
}
throw e.json();
})
);
}
export function reqapNoReload<T, U = GrpcError>(
run: () => Promise<void | T>
): Promise<[U | null, void | T | undefined]> {
return to(run());
}

36
common/ui/types.ts Normal file
View File

@ -0,0 +1,36 @@
/*
* Copyright (c) All respective contributors to the Peridot Project. All rights reserved.
* Copyright (c) 2021-2022 Rocky Enterprise Software Foundation, Inc. All rights reserved.
* Copyright (c) 2021-2022 Ctrl IQ, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
export type AccessDeniedError = 'access_denied';
export type RemoteErrors = AccessDeniedError;
export type RemoteState<T> = T | RemoteErrors | undefined | null;
export type RemoteStateList<T> = RemoteState<T[]>;

69
dotui/Alert.tsx Normal file
View File

@ -0,0 +1,69 @@
/*
* Copyright (c) All respective contributors to the Peridot Project. All rights reserved.
* Copyright (c) 2021-2022 Rocky Enterprise Software Foundation, Inc. All rights reserved.
* Copyright (c) 2021-2022 Ctrl IQ, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
import React from 'react';
import classnames from 'classnames';
import { Intent } from './intent';
export interface AlertProps {
children?: React.ReactNode;
intent?: Intent;
className?: string;
}
export const Alert = (props: AlertProps) => {
const finalIntent = props.intent || Intent.NEUTRAL;
let intentClass = 'border-gray-300 bg-white';
switch (finalIntent) {
case Intent.PRIMARY:
intentClass = 'border-peridot-primary bg-peridot-primary bg-opacity-30';
break;
case Intent.ERROR:
intentClass = 'border-red-300 bg-red-300 bg-opacity-30';
break;
case Intent.WARNING:
intentClass = 'border-yellow-300 bg-yellow-300 bg-opacity-30';
break;
case Intent.SUCCESS:
intentClass = 'border-green-300 bg-green-300 bg-opacity-30';
break;
}
return (
<div
className={classnames('p-2 rounded border', intentClass, props.className)}
>
{props.children}
</div>
);
};

16
dotui/BUILD Normal file
View File

@ -0,0 +1,16 @@
load("@raw_ts_library//:index.bzl", "raw_ts_library")
package(default_visibility = ["//visibility:public"])
raw_ts_library(
name = "dotui",
srcs = glob([
"*.ts",
"*.tsx",
]),
module_name = "dotui",
deps = [
"@npm//react",
"@npm//react-dom",
],
)

56
dotui/Card.tsx Normal file
View File

@ -0,0 +1,56 @@
/*
* Copyright (c) All respective contributors to the Peridot Project. All rights reserved.
* Copyright (c) 2021-2022 Rocky Enterprise Software Foundation, Inc. All rights reserved.
* Copyright (c) 2021-2022 Ctrl IQ, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
import React from 'react';
import classnames from 'classnames';
import { H2 } from './H2';
import { H3 } from './H3';
export interface CardProps {
children?: React.ReactNode;
title?: string;
className?: string;
}
export const Card = (props: CardProps) => {
return (
<div
className={classnames(
props.className,
'bg-white rounded p-4 border border-gray-200 text-left space-y-2'
)}
>
{props.title && <H3>{props.title}</H3>}
{props.children}
</div>
);
};

51
dotui/H1.tsx Normal file
View File

@ -0,0 +1,51 @@
/*
* Copyright (c) All respective contributors to the Peridot Project. All rights reserved.
* Copyright (c) 2021-2022 Rocky Enterprise Software Foundation, Inc. All rights reserved.
* Copyright (c) 2021-2022 Ctrl IQ, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
import React from 'react';
import classnames from 'classnames';
export interface H1Props
extends React.DetailedHTMLProps<
React.HTMLAttributes<HTMLHeadingElement>,
HTMLHeadingElement
> {
children: React.ReactNode;
}
export const H1 = (props: H1Props) => {
const { children, className, ...rest } = props;
return (
<h1 className={classnames(className, 'text-3xl font-bold')} {...rest}>
{children}
</h1>
);
};

51
dotui/H2.tsx Normal file
View File

@ -0,0 +1,51 @@
/*
* Copyright (c) All respective contributors to the Peridot Project. All rights reserved.
* Copyright (c) 2021-2022 Rocky Enterprise Software Foundation, Inc. All rights reserved.
* Copyright (c) 2021-2022 Ctrl IQ, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
import React from 'react';
import classnames from 'classnames';
export interface H1Props
extends React.DetailedHTMLProps<
React.HTMLAttributes<HTMLHeadingElement>,
HTMLHeadingElement
> {
children: React.ReactNode;
}
export const H2 = (props: H1Props) => {
const { children, className, ...rest } = props;
return (
<h1 className={classnames(className, 'text-xl font-bold')} {...rest}>
{children}
</h1>
);
};

51
dotui/H3.tsx Normal file
View File

@ -0,0 +1,51 @@
/*
* Copyright (c) All respective contributors to the Peridot Project. All rights reserved.
* Copyright (c) 2021-2022 Rocky Enterprise Software Foundation, Inc. All rights reserved.
* Copyright (c) 2021-2022 Ctrl IQ, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
import React from 'react';
import classnames from 'classnames';
export interface H1Props
extends React.DetailedHTMLProps<
React.HTMLAttributes<HTMLHeadingElement>,
HTMLHeadingElement
> {
children: React.ReactNode;
}
export const H3 = (props: H1Props) => {
const { children, className, ...rest } = props;
return (
<h1 className={classnames(className, 'text-lg font-bold')} {...rest}>
{children}
</h1>
);
};

51
dotui/H4.tsx Normal file
View File

@ -0,0 +1,51 @@
/*
* Copyright (c) All respective contributors to the Peridot Project. All rights reserved.
* Copyright (c) 2021-2022 Rocky Enterprise Software Foundation, Inc. All rights reserved.
* Copyright (c) 2021-2022 Ctrl IQ, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
import React from 'react';
import classnames from 'classnames';
export interface H1Props
extends React.DetailedHTMLProps<
React.HTMLAttributes<HTMLHeadingElement>,
HTMLHeadingElement
> {
children: React.ReactNode;
}
export const H4 = (props: H1Props) => {
const { children, className, ...rest } = props;
return (
<h1 className={classnames(className, 'text-md font-light')} {...rest}>
{children}
</h1>
);
};

51
dotui/H5.tsx Normal file
View File

@ -0,0 +1,51 @@
/*
* Copyright (c) All respective contributors to the Peridot Project. All rights reserved.
* Copyright (c) 2021-2022 Rocky Enterprise Software Foundation, Inc. All rights reserved.
* Copyright (c) 2021-2022 Ctrl IQ, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
import React from 'react';
import classnames from 'classnames';
export interface H1Props
extends React.DetailedHTMLProps<
React.HTMLAttributes<HTMLHeadingElement>,
HTMLHeadingElement
> {
children: React.ReactNode;
}
export const H5 = (props: H1Props) => {
const { children, className, ...rest } = props;
return (
<h1 className={classnames(className, 'text-sm font-light')} {...rest}>
{children}
</h1>
);
};

90
dotui/Navbar.tsx Normal file
View File

@ -0,0 +1,90 @@
/*
* Copyright (c) All respective contributors to the Peridot Project. All rights reserved.
* Copyright (c) 2021-2022 Rocky Enterprise Software Foundation, Inc. All rights reserved.
* Copyright (c) 2021-2022 Ctrl IQ, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
import React from 'react';
import { Link, NavLink } from 'react-router-dom';
import { TextField } from 'dotui/TextField';
export interface NavbarLink {
text: string;
href: string;
}
export interface NavbarProps {
mainLinks?: NavbarLink[];
subtitle?: string;
rootLink?: string;
subtitleLink?: string;
logo(classes: string): React.ReactNode;
}
export const Navbar = (props: NavbarProps) => {
return (
<div className="w-screen bg-white flex item-start justify-between">
<div className="flex items-center">
<div id="brand" className="p-2 px-4 flex">
<Link to={props.rootLink || '/'}>{props.logo('h-8 w-32')}</Link>
{props.subtitle && (
<a
id="subtitle"
className="ml-4 text-sm font-light flex items-center"
href={props.subtitleLink || '#'}
>
{props.subtitle}
</a>
)}
</div>
<div id="navigation" className="flex items-center space-x-2">
{props.mainLinks?.map((link) => (
<NavLink
className="flex items-center text-sm py-1 px-3 rounded hover:bg-gray-100 focus:bg-gray-100"
activeClassName="bg-gray-100"
to={`${props.rootLink || ''}${link.href}`}
>
{link.text}
</NavLink>
))}
</div>
</div>
<div
id="search"
className="flex items-center justify-center ml-auto mr-4"
>
<TextField placeholder label="Search" id="search" />
</div>
<div id="user" className="flex items-center justify-end mr-4 text-sm">
Mustafa Gezen
</div>
</div>
);
};

41
dotui/PageWrapper.tsx Normal file
View File

@ -0,0 +1,41 @@
/*
* Copyright (c) All respective contributors to the Peridot Project. All rights reserved.
* Copyright (c) 2021-2022 Rocky Enterprise Software Foundation, Inc. All rights reserved.
* Copyright (c) 2021-2022 Ctrl IQ, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
import React from 'react';
export interface PageWrapperProps {
children: React.ReactNode;
}
export const PageWrapper = (props: PageWrapperProps) => {
return <div className="mt-16 m-4">{props.children}</div>;
};

42
dotui/RippleLoading.tsx Normal file
View File

@ -0,0 +1,42 @@
/*
* Copyright (c) All respective contributors to the Peridot Project. All rights reserved.
* Copyright (c) 2021-2022 Rocky Enterprise Software Foundation, Inc. All rights reserved.
* Copyright (c) 2021-2022 Ctrl IQ, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
import React from 'react';
export const RippleLoading = () => {
return (
<div className="lds-ripple">
<div className="border-peridot-primary" />
<div className="border-peridot-primary" />
</div>
);
};

105
dotui/Table.tsx Normal file
View File

@ -0,0 +1,105 @@
/*
* Copyright (c) All respective contributors to the Peridot Project. All rights reserved.
* Copyright (c) 2021-2022 Rocky Enterprise Software Foundation, Inc. All rights reserved.
* Copyright (c) 2021-2022 Ctrl IQ, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
import React from 'react';
import classnames from 'classnames';
export interface TableCols {
label: string;
className?: string;
}
export interface TableProps {
cols: TableCols[];
children?: React.ReactNode;
}
export interface TableRowProps {
children?: React.ReactNode;
className?: string;
hover?: boolean;
}
export interface TableColProps {
children?: React.ReactNode;
className?: string;
}
export const Table = (props: TableProps) => {
return (
<div className="flex flex-col">
<div className="overflow-x-auto align-middle shadow sm:rounded">
<table className="w-full">
<thead>
<TableRow className="bg-gray-50">
{props.cols.map((col) => (
<TableCol
className={classnames(
'font-medium text-gray-500 tracking-wide',
col.className
)}
>
{col.label}
</TableCol>
))}
</TableRow>
</thead>
<tbody className="bg-white">{props.children}</tbody>
</table>
</div>
</div>
);
};
export const TableRow = (props: TableRowProps) => {
return (
<tr
className={classnames(
'divide-x',
props.hover && 'hover:bg-gray-50 cursor-pointer',
props.className
)}
>
{props.children}
</tr>
);
};
export const TableCol = (props: TableColProps) => {
return (
<td
className={classnames('p-3 text-sm whitespace-nowrap', props.className)}
>
{props.children}
</td>
);
};

69
dotui/TextField.tsx Normal file
View File

@ -0,0 +1,69 @@
/*
* Copyright (c) All respective contributors to the Peridot Project. All rights reserved.
* Copyright (c) 2021-2022 Rocky Enterprise Software Foundation, Inc. All rights reserved.
* Copyright (c) 2021-2022 Ctrl IQ, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
import React from 'react';
export interface TextFieldProps {
label: string;
id: string;
name?: string;
placeholder?: boolean;
type?: string;
required?: boolean;
onChange?(e: React.ChangeEvent<HTMLInputElement>): void;
}
export const TextField = (props: TextFieldProps) => {
return (
<div className="w-full">
{!props.placeholder && (
<label
htmlFor={props.id}
className="block text-sm font-medium text-gray-700"
>
{props.label}
</label>
)}
<div className={!props.placeholder ? 'mt-1' : undefined}>
<input
type={props.type || 'text'}
required={props.required}
name={props.name}
id={props.id}
className="shadow-sm focus:ring-gray-300 focus:border-gray-300 block w-full sm:text-sm border-gray-200 rounded-md text-sm leading-3"
placeholder={props.placeholder ? props.label : undefined}
onChange={props.onChange}
/>
</div>
</div>
);
};

33
dotui/index.ts Normal file
View File

@ -0,0 +1,33 @@
/*
* Copyright (c) All respective contributors to the Peridot Project. All rights reserved.
* Copyright (c) 2021-2022 Rocky Enterprise Software Foundation, Inc. All rights reserved.
* Copyright (c) 2021-2022 Ctrl IQ, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
export * from './Navbar';

39
dotui/intent.ts Normal file
View File

@ -0,0 +1,39 @@
/*
* Copyright (c) All respective contributors to the Peridot Project. All rights reserved.
* Copyright (c) 2021-2022 Rocky Enterprise Software Foundation, Inc. All rights reserved.
* Copyright (c) 2021-2022 Ctrl IQ, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
export enum Intent {
NEUTRAL = 0,
SUCCESS = 1,
WARNING = 2,
ERROR = 3,
PRIMARY = 4,
}

87
go.mod Normal file
View File

@ -0,0 +1,87 @@
//gen:comment:this file is generated with nofussvendor. DO NOT EDIT
module peridot.resf.org
go 1.15
require (
alexejk.io/go-xmlrpc v0.2.0
bazel.build/protobuf v0.0.0-00010101000000-000000000000
cirello.io/dynamolock v1.4.0
github.com/ProtonMail/go-crypto v0.0.0-20220113124808-70ae35bab23f
github.com/ProtonMail/gopenpgp/v2 v2.4.7
github.com/PuerkitoBio/goquery v1.7.0
github.com/antchfx/xmlquery v1.3.6 // indirect
github.com/authzed/authzed-go v0.3.0
github.com/authzed/grpcutil v0.0.0-20211115181027-063820eb2511 // indirect
github.com/aws/aws-sdk-go v1.36.12
github.com/cavaliergopher/rpm v1.2.0
github.com/coreos/go-oidc/v3 v3.0.0
github.com/creack/pty v1.1.18 // indirect
github.com/docker/docker v20.10.14+incompatible // indirect
github.com/fatih/color v1.12.0
github.com/go-chi/chi v4.1.2+incompatible
github.com/go-git/go-billy/v5 v5.3.1
github.com/go-git/go-git/v5 v5.2.0
github.com/go-openapi/runtime v0.19.31
github.com/go-openapi/strfmt v0.20.2
github.com/gobwas/glob v0.2.3
github.com/gocolly/colly/v2 v2.1.0
github.com/gogo/status v1.1.0
github.com/google/uuid v1.3.0
github.com/gosimple/slug v1.12.0 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.6.0
github.com/imdario/mergo v0.3.11 // indirect
github.com/jedib0t/go-pretty/v6 v6.2.7 // indirect
github.com/jmoiron/sqlx v1.3.4
github.com/lib/pq v1.10.2
github.com/mattn/go-tty v0.0.4 // indirect
github.com/ory/hydra-client-go v1.10.6
github.com/pelletier/go-toml v1.8.1 // indirect
github.com/rocky-linux/srpmproc v0.3.16
github.com/sirupsen/logrus v1.8.1
github.com/spf13/cobra v1.1.3
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.7.1
github.com/stretchr/testify v1.7.0
github.com/temoto/robotstxt v1.1.2 // indirect
github.com/uber/jaeger-client-go v2.29.1+incompatible // indirect
github.com/vbauerster/mpb/v7 v7.0.2
github.com/vishvananda/netlink v1.1.0 // indirect
github.com/xanzy/go-gitlab v0.50.4
go.temporal.io/api v1.6.1-0.20211110205628-60c98e9cbfe2
go.temporal.io/sdk v1.13.1
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f
golang.org/x/sys v0.0.0-20211110154304-99a53858aa08
google.golang.org/genproto v0.0.0-20211104193956-4c6863e31247
google.golang.org/grpc v1.44.0
google.golang.org/protobuf v1.27.1
gopkg.in/ini.v1 v1.57.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
k8s.io/api v0.22.1
k8s.io/apimachinery v0.22.1
k8s.io/client-go v0.22.1
kernel.org/pub/linux/libs/security/libcap/cap v1.2.64 // indirect
peridot.resf.org/common v0.0.0-00010101000000-000000000000
peridot.resf.org/obsidian/pb v0.0.0-00010101000000-000000000000
peridot.resf.org/peridot/keykeeper/pb v0.0.0-00010101000000-000000000000
peridot.resf.org/peridot/pb v0.0.0-00010101000000-000000000000
peridot.resf.org/peridot/yumrepofs/pb v0.0.0-00010101000000-000000000000
peridot.resf.org/secparse/admin/proto v0.0.0-00010101000000-000000000000
peridot.resf.org/secparse/proto v0.0.0-00010101000000-000000000000
)
// sync-replace-start
replace (
bazel.build/protobuf => ./bazel-bin/build/bazel/protobuf/bazelbuild_go_proto_/bazel.build/protobuf
bazel.build/remote/execution/v2 => ./bazel-bin/build/bazel/remote/execution/v2/remoteexecution_go_proto_/bazel.build/remote/execution/v2
bazel.build/semver => ./bazel-bin/build/bazel/semver/semver_go_proto_/bazel.build/semver
peridot.resf.org/obsidian/pb => ./bazel-bin/obsidian/proto/v1/obsidianpb_go_proto_/peridot.resf.org/obsidian/pb
peridot.resf.org/peridot/pb => ./bazel-bin/peridot/proto/v1/peridotpb_go_proto_/peridot.resf.org/peridot/pb
peridot.resf.org/peridot/keykeeper/pb => ./bazel-bin/peridot/proto/v1/keykeeper/keykeeperpb_go_proto_/peridot.resf.org/peridot/keykeeper/pb
peridot.resf.org/peridot/yumrepofs/pb => ./bazel-bin/peridot/proto/v1/yumrepofs/yumrepofspb_go_proto_/peridot.resf.org/peridot/yumrepofs/pb
peridot.resf.org/common => ./bazel-bin/proto/commonpb_go_proto_/peridot.resf.org/common
peridot.resf.org/secparse/admin/proto => ./bazel-bin/secparse/admin/proto/v1/secparseadminpb_go_proto_/peridot.resf.org/secparse/admin/proto
peridot.resf.org/secparse/proto => ./bazel-bin/secparse/proto/v1/secparsepb_go_proto_/peridot.resf.org/secparse/proto
github.com/envoyproxy/protoc-gen-validate/validate => ./bazel-bin/vendor/github.com/envoyproxy/protoc-gen-validate/validate/go_default_library_/github.com/envoyproxy/protoc-gen-validate/validate
)
// sync-replace-end

1313
go.sum Normal file

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More