Refactored airshipctl config
Removed Modules from config. There are no other types of modules that need additional configuration. BootstrapInfo is defined in the config directly. Used camelCase for config parameters. Change-Id: I3531a061026f3b2f1e72af6272ba4709f28d1b3d
This commit is contained in:
parent
68c97923e1
commit
cd9b4dddb4
@ -1,7 +1,7 @@
|
||||
Cluster: clusterBar
|
||||
ephemeral:
|
||||
bootstrap-info: ""
|
||||
cluster-kubeconf: clusterBar_ephemeral
|
||||
bootstrapInfo: ""
|
||||
clusterKubeconf: clusterBar_ephemeral
|
||||
|
||||
LocationOfOrigin: ""
|
||||
insecure-skip-tls-verify: true
|
||||
@ -9,8 +9,8 @@ server: ""
|
||||
|
||||
Cluster: clusterBar
|
||||
target:
|
||||
bootstrap-info: ""
|
||||
cluster-kubeconf: clusterBar_target
|
||||
bootstrapInfo: ""
|
||||
clusterKubeconf: clusterBar_target
|
||||
|
||||
LocationOfOrigin: ""
|
||||
insecure-skip-tls-verify: true
|
||||
@ -18,8 +18,8 @@ server: ""
|
||||
|
||||
Cluster: clusterBaz
|
||||
ephemeral:
|
||||
bootstrap-info: ""
|
||||
cluster-kubeconf: clusterBaz_ephemeral
|
||||
bootstrapInfo: ""
|
||||
clusterKubeconf: clusterBaz_ephemeral
|
||||
|
||||
LocationOfOrigin: ""
|
||||
insecure-skip-tls-verify: true
|
||||
@ -27,8 +27,8 @@ server: ""
|
||||
|
||||
Cluster: clusterBaz
|
||||
target:
|
||||
bootstrap-info: ""
|
||||
cluster-kubeconf: clusterBaz_target
|
||||
bootstrapInfo: ""
|
||||
clusterKubeconf: clusterBaz_target
|
||||
|
||||
LocationOfOrigin: ""
|
||||
insecure-skip-tls-verify: true
|
||||
@ -36,8 +36,8 @@ server: ""
|
||||
|
||||
Cluster: clusterFoo
|
||||
ephemeral:
|
||||
bootstrap-info: ""
|
||||
cluster-kubeconf: clusterFoo_ephemeral
|
||||
bootstrapInfo: ""
|
||||
clusterKubeconf: clusterFoo_ephemeral
|
||||
|
||||
LocationOfOrigin: ""
|
||||
insecure-skip-tls-verify: true
|
||||
@ -45,8 +45,8 @@ server: ""
|
||||
|
||||
Cluster: clusterFoo
|
||||
target:
|
||||
bootstrap-info: ""
|
||||
cluster-kubeconf: clusterFoo_target
|
||||
bootstrapInfo: ""
|
||||
clusterKubeconf: clusterFoo_target
|
||||
|
||||
LocationOfOrigin: ""
|
||||
insecure-skip-tls-verify: true
|
||||
|
@ -1,7 +1,7 @@
|
||||
Cluster: clusterBar
|
||||
ephemeral:
|
||||
bootstrap-info: ""
|
||||
cluster-kubeconf: clusterBar_ephemeral
|
||||
bootstrapInfo: ""
|
||||
clusterKubeconf: clusterBar_ephemeral
|
||||
|
||||
LocationOfOrigin: ""
|
||||
insecure-skip-tls-verify: true
|
||||
@ -9,8 +9,8 @@ server: ""
|
||||
|
||||
Cluster: clusterBar
|
||||
target:
|
||||
bootstrap-info: ""
|
||||
cluster-kubeconf: clusterBar_target
|
||||
bootstrapInfo: ""
|
||||
clusterKubeconf: clusterBar_target
|
||||
|
||||
LocationOfOrigin: ""
|
||||
insecure-skip-tls-verify: true
|
||||
@ -18,8 +18,8 @@ server: ""
|
||||
|
||||
Cluster: clusterBaz
|
||||
ephemeral:
|
||||
bootstrap-info: ""
|
||||
cluster-kubeconf: clusterBaz_ephemeral
|
||||
bootstrapInfo: ""
|
||||
clusterKubeconf: clusterBaz_ephemeral
|
||||
|
||||
LocationOfOrigin: ""
|
||||
insecure-skip-tls-verify: true
|
||||
@ -27,8 +27,8 @@ server: ""
|
||||
|
||||
Cluster: clusterBaz
|
||||
target:
|
||||
bootstrap-info: ""
|
||||
cluster-kubeconf: clusterBaz_target
|
||||
bootstrapInfo: ""
|
||||
clusterKubeconf: clusterBaz_target
|
||||
|
||||
LocationOfOrigin: ""
|
||||
insecure-skip-tls-verify: true
|
||||
@ -36,8 +36,8 @@ server: ""
|
||||
|
||||
Cluster: clusterFoo
|
||||
ephemeral:
|
||||
bootstrap-info: ""
|
||||
cluster-kubeconf: clusterFoo_ephemeral
|
||||
bootstrapInfo: ""
|
||||
clusterKubeconf: clusterFoo_ephemeral
|
||||
|
||||
LocationOfOrigin: ""
|
||||
insecure-skip-tls-verify: true
|
||||
@ -45,8 +45,8 @@ server: ""
|
||||
|
||||
Cluster: clusterFoo
|
||||
target:
|
||||
bootstrap-info: ""
|
||||
cluster-kubeconf: clusterFoo_target
|
||||
bootstrapInfo: ""
|
||||
clusterKubeconf: clusterFoo_target
|
||||
|
||||
LocationOfOrigin: ""
|
||||
insecure-skip-tls-verify: true
|
||||
|
@ -1,7 +1,7 @@
|
||||
Cluster: clusterFoo
|
||||
ephemeral:
|
||||
bootstrap-info: ""
|
||||
cluster-kubeconf: clusterFoo_ephemeral
|
||||
bootstrapInfo: ""
|
||||
clusterKubeconf: clusterFoo_ephemeral
|
||||
|
||||
LocationOfOrigin: ""
|
||||
insecure-skip-tls-verify: true
|
||||
|
@ -1,7 +1,7 @@
|
||||
Cluster: clusterBar
|
||||
ephemeral:
|
||||
bootstrap-info: ""
|
||||
cluster-kubeconf: clusterBar_ephemeral
|
||||
bootstrapInfo: ""
|
||||
clusterKubeconf: clusterBar_ephemeral
|
||||
|
||||
LocationOfOrigin: ""
|
||||
insecure-skip-tls-verify: true
|
||||
@ -9,8 +9,8 @@ server: ""
|
||||
|
||||
Cluster: clusterBar
|
||||
target:
|
||||
bootstrap-info: ""
|
||||
cluster-kubeconf: clusterBar_target
|
||||
bootstrapInfo: ""
|
||||
clusterKubeconf: clusterBar_target
|
||||
|
||||
LocationOfOrigin: ""
|
||||
insecure-skip-tls-verify: true
|
||||
@ -18,8 +18,8 @@ server: ""
|
||||
|
||||
Cluster: clusterBaz
|
||||
ephemeral:
|
||||
bootstrap-info: ""
|
||||
cluster-kubeconf: clusterBaz_ephemeral
|
||||
bootstrapInfo: ""
|
||||
clusterKubeconf: clusterBaz_ephemeral
|
||||
|
||||
LocationOfOrigin: ""
|
||||
insecure-skip-tls-verify: true
|
||||
@ -27,8 +27,8 @@ server: ""
|
||||
|
||||
Cluster: clusterBaz
|
||||
target:
|
||||
bootstrap-info: ""
|
||||
cluster-kubeconf: clusterBaz_target
|
||||
bootstrapInfo: ""
|
||||
clusterKubeconf: clusterBaz_target
|
||||
|
||||
LocationOfOrigin: ""
|
||||
insecure-skip-tls-verify: true
|
||||
@ -36,8 +36,8 @@ server: ""
|
||||
|
||||
Cluster: clusterFoo
|
||||
ephemeral:
|
||||
bootstrap-info: ""
|
||||
cluster-kubeconf: clusterFoo_ephemeral
|
||||
bootstrapInfo: ""
|
||||
clusterKubeconf: clusterFoo_ephemeral
|
||||
|
||||
LocationOfOrigin: ""
|
||||
insecure-skip-tls-verify: true
|
||||
@ -45,8 +45,8 @@ server: ""
|
||||
|
||||
Cluster: clusterFoo
|
||||
target:
|
||||
bootstrap-info: ""
|
||||
cluster-kubeconf: clusterFoo_target
|
||||
bootstrapInfo: ""
|
||||
clusterKubeconf: clusterFoo_target
|
||||
|
||||
LocationOfOrigin: ""
|
||||
insecure-skip-tls-verify: true
|
||||
|
@ -1,7 +1,7 @@
|
||||
Cluster: clusterBar
|
||||
ephemeral:
|
||||
bootstrap-info: ""
|
||||
cluster-kubeconf: clusterBar_ephemeral
|
||||
bootstrapInfo: ""
|
||||
clusterKubeconf: clusterBar_ephemeral
|
||||
|
||||
LocationOfOrigin: ""
|
||||
insecure-skip-tls-verify: true
|
||||
@ -9,8 +9,8 @@ server: ""
|
||||
|
||||
Cluster: clusterBar
|
||||
target:
|
||||
bootstrap-info: ""
|
||||
cluster-kubeconf: clusterBar_target
|
||||
bootstrapInfo: ""
|
||||
clusterKubeconf: clusterBar_target
|
||||
|
||||
LocationOfOrigin: ""
|
||||
insecure-skip-tls-verify: true
|
||||
@ -18,8 +18,8 @@ server: ""
|
||||
|
||||
Cluster: clusterBaz
|
||||
ephemeral:
|
||||
bootstrap-info: ""
|
||||
cluster-kubeconf: clusterBaz_ephemeral
|
||||
bootstrapInfo: ""
|
||||
clusterKubeconf: clusterBaz_ephemeral
|
||||
|
||||
LocationOfOrigin: ""
|
||||
insecure-skip-tls-verify: true
|
||||
@ -27,8 +27,8 @@ server: ""
|
||||
|
||||
Cluster: clusterBaz
|
||||
target:
|
||||
bootstrap-info: ""
|
||||
cluster-kubeconf: clusterBaz_target
|
||||
bootstrapInfo: ""
|
||||
clusterKubeconf: clusterBaz_target
|
||||
|
||||
LocationOfOrigin: ""
|
||||
insecure-skip-tls-verify: true
|
||||
@ -36,8 +36,8 @@ server: ""
|
||||
|
||||
Cluster: clusterFoo
|
||||
ephemeral:
|
||||
bootstrap-info: ""
|
||||
cluster-kubeconf: clusterFoo_ephemeral
|
||||
bootstrapInfo: ""
|
||||
clusterKubeconf: clusterFoo_ephemeral
|
||||
|
||||
LocationOfOrigin: ""
|
||||
insecure-skip-tls-verify: true
|
||||
@ -45,8 +45,8 @@ server: ""
|
||||
|
||||
Cluster: clusterFoo
|
||||
target:
|
||||
bootstrap-info: ""
|
||||
cluster-kubeconf: clusterFoo_target
|
||||
bootstrapInfo: ""
|
||||
clusterKubeconf: clusterFoo_target
|
||||
|
||||
LocationOfOrigin: ""
|
||||
insecure-skip-tls-verify: true
|
||||
|
@ -1,7 +1,7 @@
|
||||
Cluster: clusterFoo
|
||||
target:
|
||||
bootstrap-info: ""
|
||||
cluster-kubeconf: clusterFoo_target
|
||||
bootstrapInfo: ""
|
||||
clusterKubeconf: clusterFoo_target
|
||||
|
||||
LocationOfOrigin: ""
|
||||
insecure-skip-tls-verify: true
|
||||
|
@ -1,5 +1,5 @@
|
||||
Context: ContextBar
|
||||
context-kubeconf: ContextBar_ephemeral
|
||||
contextKubeconf: ContextBar_ephemeral
|
||||
manifest: Manifest_ContextBar
|
||||
|
||||
LocationOfOrigin: ""
|
||||
@ -9,7 +9,7 @@ user: dummy_user
|
||||
|
||||
|
||||
Context: ContextBaz
|
||||
context-kubeconf: ContextBaz_ephemeral
|
||||
contextKubeconf: ContextBaz_ephemeral
|
||||
manifest: Manifest_ContextBaz
|
||||
|
||||
LocationOfOrigin: ""
|
||||
@ -19,7 +19,7 @@ user: dummy_user
|
||||
|
||||
|
||||
Context: ContextFoo
|
||||
context-kubeconf: ContextFoo_ephemeral
|
||||
contextKubeconf: ContextFoo_ephemeral
|
||||
manifest: Manifest_ContextFoo
|
||||
|
||||
LocationOfOrigin: ""
|
||||
|
@ -1,5 +1,5 @@
|
||||
Context: ContextFoo
|
||||
context-kubeconf: ContextFoo_ephemeral
|
||||
contextKubeconf: ContextFoo_ephemeral
|
||||
manifest: Manifest_ContextFoo
|
||||
|
||||
LocationOfOrigin: ""
|
||||
|
@ -1,5 +1,5 @@
|
||||
Context: ContextBaz
|
||||
context-kubeconf: ContextBaz_ephemeral
|
||||
contextKubeconf: ContextBaz_ephemeral
|
||||
manifest: Manifest_ContextBaz
|
||||
|
||||
LocationOfOrigin: ""
|
||||
|
@ -1,5 +1,5 @@
|
||||
Context: ContextBar
|
||||
context-kubeconf: ContextBar_ephemeral
|
||||
contextKubeconf: ContextBar_ephemeral
|
||||
manifest: Manifest_ContextBar
|
||||
|
||||
LocationOfOrigin: ""
|
||||
@ -9,7 +9,7 @@ user: dummy_user
|
||||
|
||||
|
||||
Context: ContextBaz
|
||||
context-kubeconf: ContextBaz_ephemeral
|
||||
contextKubeconf: ContextBaz_ephemeral
|
||||
manifest: Manifest_ContextBaz
|
||||
|
||||
LocationOfOrigin: ""
|
||||
@ -19,7 +19,7 @@ user: dummy_user
|
||||
|
||||
|
||||
Context: ContextFoo
|
||||
context-kubeconf: ContextFoo_ephemeral
|
||||
contextKubeconf: ContextFoo_ephemeral
|
||||
manifest: Manifest_ContextFoo
|
||||
|
||||
LocationOfOrigin: ""
|
||||
|
62
pkg/cluster/initinfra/testdata/config.yaml
vendored
62
pkg/cluster/initinfra/testdata/config.yaml
vendored
@ -1,34 +1,5 @@
|
||||
apiVersion: airshipit.org/v1alpha1
|
||||
clusters:
|
||||
dummycluster:
|
||||
cluster-type:
|
||||
ephemeral:
|
||||
bootstrap-info: dummy_bootstrap_config
|
||||
cluster-kubeconf: dummycluster_ephemeral
|
||||
contexts:
|
||||
dummy_cluster:
|
||||
context-kubeconf: dummy_cluster
|
||||
manifest: dummy_manifest
|
||||
current-context: dummy_cluster
|
||||
kind: Config
|
||||
manifests:
|
||||
dummy_manifest:
|
||||
primary-repository-name: primary
|
||||
repositories:
|
||||
primary:
|
||||
auth:
|
||||
ssh-key: testdata/test-key.pem
|
||||
type: ssh-key
|
||||
checkout:
|
||||
branch: ""
|
||||
force: false
|
||||
remote-ref: ""
|
||||
tag: v1.0.1
|
||||
url: http://dummy.url.com/primary.git
|
||||
sub-path: primary/site/test-site
|
||||
target-path: testdata
|
||||
modules-config:
|
||||
bootstrapInfo:
|
||||
bootstrapInfo:
|
||||
dummy_bootstrap_config:
|
||||
container:
|
||||
volume: /tmp/airship:/config
|
||||
@ -38,5 +9,36 @@ modules-config:
|
||||
userDataFileName: user-data
|
||||
networkConfigFileName: network-config
|
||||
outputMetadataFileName: output-metadata.yaml
|
||||
remoteDirect:
|
||||
isoUrl: http://localhost:8099/debian-custom.iso
|
||||
remoteType: redfish
|
||||
clusters:
|
||||
dummycluster:
|
||||
clusterType:
|
||||
ephemeral:
|
||||
bootstrapInfo: dummy_bootstrap_config
|
||||
clusterKubeconf: dummycluster_ephemeral
|
||||
contexts:
|
||||
dummy_cluster:
|
||||
contextKubeconf: dummy_cluster
|
||||
manifest: dummy_manifest
|
||||
currentContext: dummy_cluster
|
||||
kind: Config
|
||||
manifests:
|
||||
dummy_manifest:
|
||||
primaryRepositoryName: primary
|
||||
repositories:
|
||||
primary:
|
||||
auth:
|
||||
sshKey: testdata/test-key.pem
|
||||
type: ssh-key
|
||||
checkout:
|
||||
branch: ""
|
||||
force: false
|
||||
remoteRef: ""
|
||||
tag: v1.0.1
|
||||
url: http://dummy.url.com/primary.git
|
||||
subPath: primary/site/test-site
|
||||
targetPath: testdata
|
||||
users:
|
||||
dummy_user: {}
|
@ -716,11 +716,11 @@ func (c *Config) CurrentContextBootstrapInfo() (*Bootstrap, error) {
|
||||
|
||||
if currentCluster.Bootstrap == "" {
|
||||
return nil, ErrMissingConfig{
|
||||
What: fmt.Sprintf("No bootstrap-info defined for context %q", c.CurrentContext),
|
||||
What: fmt.Sprintf("No bootstrapInfo defined for context %q", c.CurrentContext),
|
||||
}
|
||||
}
|
||||
|
||||
bootstrap, exists := c.ModulesConfig.BootstrapInfo[currentCluster.Bootstrap]
|
||||
bootstrap, exists := c.BootstrapInfo[currentCluster.Bootstrap]
|
||||
if !exists {
|
||||
return nil, ErrBootstrapInfoNotFound{Name: currentCluster.Bootstrap}
|
||||
}
|
||||
@ -815,15 +815,6 @@ func (m *Manifest) String() string {
|
||||
return string(yamlData)
|
||||
}
|
||||
|
||||
// Modules functions
|
||||
func (m *Modules) String() string {
|
||||
yamlData, err := yaml.Marshal(&m)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return string(yamlData)
|
||||
}
|
||||
|
||||
// Bootstrap functions
|
||||
func (b *Bootstrap) String() string {
|
||||
yamlData, err := yaml.Marshal(&b)
|
||||
|
@ -61,10 +61,6 @@ func TestString(t *testing.T) {
|
||||
name: "manifest",
|
||||
stringer: testutil.DummyManifest(),
|
||||
},
|
||||
{
|
||||
name: "modules",
|
||||
stringer: testutil.DummyModules(),
|
||||
},
|
||||
{
|
||||
name: "repository",
|
||||
stringer: testutil.DummyRepository(),
|
||||
@ -78,12 +74,8 @@ func TestString(t *testing.T) {
|
||||
stringer: testutil.DummyRepoCheckout(),
|
||||
},
|
||||
{
|
||||
name: "bootstrap",
|
||||
stringer: testutil.DummyBootstrap(),
|
||||
},
|
||||
{
|
||||
name: "bootstrap",
|
||||
stringer: testutil.DummyBootstrap(),
|
||||
name: "bootstrapinfo",
|
||||
stringer: testutil.DummyBootstrapInfo(),
|
||||
},
|
||||
{
|
||||
name: "builder",
|
||||
@ -282,7 +274,7 @@ func TestCurrentContextBootstrapInfo(t *testing.T) {
|
||||
|
||||
bootstrapInfo, err = conf.CurrentContextBootstrapInfo()
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, conf.ModulesConfig.BootstrapInfo[defaultString], bootstrapInfo)
|
||||
assert.Equal(t, conf.BootstrapInfo[defaultString], bootstrapInfo)
|
||||
}
|
||||
|
||||
func TestPurge(t *testing.T) {
|
||||
|
@ -42,7 +42,7 @@ const (
|
||||
url: git@github.com:go-git/go-git.git
|
||||
auth:
|
||||
type: ssh-key
|
||||
ssh-key: "testdata/test-key.pem"
|
||||
sshKey: "testdata/test-key.pem"
|
||||
username: git
|
||||
checkout:
|
||||
branch: master
|
||||
@ -50,62 +50,62 @@ const (
|
||||
url: /home/ubuntu/some-gitrepo
|
||||
auth:
|
||||
type: ssh-pass
|
||||
ssh-pass: "qwerty123"
|
||||
sshPass: "qwerty123"
|
||||
username: deployer
|
||||
checkout:
|
||||
commit-hash: 01c4f7f32beb9851ae8f119a6b8e497d2b1e2bb8
|
||||
commitHash: 01c4f7f32beb9851ae8f119a6b8e497d2b1e2bb8
|
||||
http-basic-auth:
|
||||
url: /home/ubuntu/some-gitrepo
|
||||
auth:
|
||||
type: http-basic
|
||||
http-pass: "qwerty123"
|
||||
httpPass: "qwerty123"
|
||||
username: deployer
|
||||
checkout:
|
||||
commit-hash: 01c4f7f32beb9851ae8f119a6b8e497d2b1e2bb8
|
||||
commitHash: 01c4f7f32beb9851ae8f119a6b8e497d2b1e2bb8
|
||||
empty-checkout:
|
||||
url: /home/ubuntu/some-gitrepo
|
||||
auth:
|
||||
type: http-basic
|
||||
http-pass: "qwerty123"
|
||||
httpPass: "qwerty123"
|
||||
username: deployer
|
||||
wrong-type-auth:
|
||||
url: /home/ubuntu/some-gitrepo
|
||||
auth:
|
||||
type: wrong-type
|
||||
http-pass: "qwerty123"
|
||||
httpPass: "qwerty123"
|
||||
username: deployer
|
||||
checkout:
|
||||
commit-hash: 01c4f7f32beb9851ae8f119a6b8e497d2b1e2bb8
|
||||
commitHash: 01c4f7f32beb9851ae8f119a6b8e497d2b1e2bb8
|
||||
mutually-exclusive-auth-opts:
|
||||
url: /home/ubuntu/some-gitrepo
|
||||
auth:
|
||||
type: http-basic
|
||||
ssh-key: "/path-to-key"
|
||||
sshKey: "/path-to-key"
|
||||
username: deployer
|
||||
mutually-exclusive-checkout-opts:
|
||||
url: /home/ubuntu/some-gitrepo
|
||||
checkout:
|
||||
commit-hash: 01c4f7f32beb9851ae8f119a6b8e497d2b1e2bb8
|
||||
commitHash: 01c4f7f32beb9851ae8f119a6b8e497d2b1e2bb8
|
||||
branch: master
|
||||
mutually-exclusive-auth-opts-ssh-key:
|
||||
url: /home/ubuntu/some-gitrepo
|
||||
auth:
|
||||
type: ssh-key
|
||||
http-pass: "qwerty123"
|
||||
ssh-key: "/path-to-key"
|
||||
httpPass: "qwerty123"
|
||||
sshKey: "/path-to-key"
|
||||
username: deployer
|
||||
checkout:
|
||||
commit-hash: 01c4f7f32beb9851ae8f119a6b8e497d2b1e2bb8
|
||||
commitHash: 01c4f7f32beb9851ae8f119a6b8e497d2b1e2bb8
|
||||
mutually-exclusive-auth-opts-ssh-pass:
|
||||
url: /home/ubuntu/some-gitrepo
|
||||
auth:
|
||||
type: ssh-pass
|
||||
ssh-pass: "qwerty123"
|
||||
http-pass: "qwerty123"
|
||||
ssh-key: "/path-to-key"
|
||||
sshPass: "qwerty123"
|
||||
httpPass: "qwerty123"
|
||||
sshKey: "/path-to-key"
|
||||
username: deployer
|
||||
checkout:
|
||||
commit-hash: 01c4f7f32beb9851ae8f119a6b8e497d2b1e2bb8`
|
||||
commitHash: 01c4f7f32beb9851ae8f119a6b8e497d2b1e2bb8`
|
||||
)
|
||||
|
||||
var (
|
||||
|
4
pkg/config/testdata/cluster-string.yaml
vendored
4
pkg/config/testdata/cluster-string.yaml
vendored
@ -1,5 +1,5 @@
|
||||
bootstrap-info: dummy_bootstrap_config
|
||||
cluster-kubeconf: dummy_cluster_target
|
||||
bootstrapInfo: dummy_bootstrap_config
|
||||
clusterKubeconf: dummy_cluster_target
|
||||
|
||||
LocationOfOrigin: ""
|
||||
certificate-authority: dummy_ca
|
||||
|
65
pkg/config/testdata/config-string.yaml
vendored
65
pkg/config/testdata/config-string.yaml
vendored
@ -1,37 +1,5 @@
|
||||
apiVersion: airshipit.org/v1alpha1
|
||||
clusters:
|
||||
dummy_cluster:
|
||||
cluster-type:
|
||||
ephemeral:
|
||||
bootstrap-info: dummy_bootstrap_config
|
||||
cluster-kubeconf: dummy_cluster_ephemeral
|
||||
target:
|
||||
bootstrap-info: dummy_bootstrap_config
|
||||
cluster-kubeconf: dummy_cluster_target
|
||||
contexts:
|
||||
dummy_context:
|
||||
context-kubeconf: dummy_cluster_ephemeral
|
||||
manifest: dummy_manifest
|
||||
current-context: dummy_context
|
||||
kind: Config
|
||||
manifests:
|
||||
dummy_manifest:
|
||||
primary-repository-name: primary
|
||||
repositories:
|
||||
primary:
|
||||
auth:
|
||||
ssh-key: testdata/test-key.pem
|
||||
type: ssh-key
|
||||
checkout:
|
||||
branch: ""
|
||||
force: false
|
||||
remote-ref: ""
|
||||
tag: v1.0.1
|
||||
url: http://dummy.url.com/manifests.git
|
||||
sub-path: manifests/site/test-site
|
||||
target-path: /var/tmp/
|
||||
modules-config:
|
||||
bootstrapInfo:
|
||||
bootstrapInfo:
|
||||
dummy_bootstrap_config:
|
||||
builder:
|
||||
networkConfigFileName: netconfig
|
||||
@ -41,5 +9,36 @@ modules-config:
|
||||
containerRuntime: docker
|
||||
image: dummy_image:dummy_tag
|
||||
volume: /dummy:dummy
|
||||
clusters:
|
||||
dummy_cluster:
|
||||
clusterType:
|
||||
ephemeral:
|
||||
bootstrapInfo: dummy_bootstrap_config
|
||||
clusterKubeconf: dummy_cluster_ephemeral
|
||||
target:
|
||||
bootstrapInfo: dummy_bootstrap_config
|
||||
clusterKubeconf: dummy_cluster_target
|
||||
contexts:
|
||||
dummy_context:
|
||||
contextKubeconf: dummy_cluster_ephemeral
|
||||
manifest: dummy_manifest
|
||||
currentContext: dummy_context
|
||||
kind: Config
|
||||
manifests:
|
||||
dummy_manifest:
|
||||
primaryRepositoryName: primary
|
||||
repositories:
|
||||
primary:
|
||||
auth:
|
||||
sshKey: testdata/test-key.pem
|
||||
type: ssh-key
|
||||
checkout:
|
||||
branch: ""
|
||||
force: false
|
||||
remoteRef: ""
|
||||
tag: v1.0.1
|
||||
url: http://dummy.url.com/manifests.git
|
||||
subPath: manifests/site/test-site
|
||||
targetPath: /var/tmp/
|
||||
users:
|
||||
dummy_user: {}
|
||||
|
2
pkg/config/testdata/context-string.yaml
vendored
2
pkg/config/testdata/context-string.yaml
vendored
@ -1,4 +1,4 @@
|
||||
context-kubeconf: dummy_cluster_ephemeral
|
||||
contextKubeconf: dummy_cluster_ephemeral
|
||||
manifest: dummy_manifest
|
||||
|
||||
LocationOfOrigin: ""
|
||||
|
10
pkg/config/testdata/manifest-string.yaml
vendored
10
pkg/config/testdata/manifest-string.yaml
vendored
@ -1,14 +1,14 @@
|
||||
primary-repository-name: primary
|
||||
primaryRepositoryName: primary
|
||||
repositories:
|
||||
primary:
|
||||
auth:
|
||||
ssh-key: testdata/test-key.pem
|
||||
sshKey: testdata/test-key.pem
|
||||
type: ssh-key
|
||||
checkout:
|
||||
branch: ""
|
||||
force: false
|
||||
remote-ref: ""
|
||||
remoteRef: ""
|
||||
tag: v1.0.1
|
||||
url: http://dummy.url.com/manifests.git
|
||||
sub-path: manifests/site/test-site
|
||||
target-path: /var/tmp/
|
||||
subPath: manifests/site/test-site
|
||||
targetPath: /var/tmp/
|
||||
|
10
pkg/config/testdata/modules-string.yaml
vendored
10
pkg/config/testdata/modules-string.yaml
vendored
@ -1,10 +0,0 @@
|
||||
bootstrapInfo:
|
||||
dummy_bootstrap_config:
|
||||
builder:
|
||||
networkConfigFileName: netconfig
|
||||
outputMetadataFileName: output-metadata.yaml
|
||||
userDataFileName: user-data
|
||||
container:
|
||||
containerRuntime: docker
|
||||
image: dummy_image:dummy_tag
|
||||
volume: /dummy:dummy
|
@ -1,7 +1,7 @@
|
||||
Cluster: dummy_cluster
|
||||
target:
|
||||
bootstrap-info: dummy_bootstrap_config
|
||||
cluster-kubeconf: dummy_cluster_target
|
||||
bootstrapInfo: dummy_bootstrap_config
|
||||
clusterKubeconf: dummy_cluster_target
|
||||
|
||||
LocationOfOrigin: ""
|
||||
certificate-authority: dummy_ca
|
||||
|
2
pkg/config/testdata/repo-auth-string.yaml
vendored
2
pkg/config/testdata/repo-auth-string.yaml
vendored
@ -1,2 +1,2 @@
|
||||
ssh-key: testdata/test-key.pem
|
||||
sshKey: testdata/test-key.pem
|
||||
type: ssh-key
|
||||
|
@ -1,4 +1,4 @@
|
||||
branch: ""
|
||||
force: false
|
||||
remote-ref: ""
|
||||
remoteRef: ""
|
||||
tag: v1.0.1
|
||||
|
4
pkg/config/testdata/repository-string.yaml
vendored
4
pkg/config/testdata/repository-string.yaml
vendored
@ -1,9 +1,9 @@
|
||||
auth:
|
||||
ssh-key: testdata/test-key.pem
|
||||
sshKey: testdata/test-key.pem
|
||||
type: ssh-key
|
||||
checkout:
|
||||
branch: ""
|
||||
force: false
|
||||
remote-ref: ""
|
||||
remoteRef: ""
|
||||
tag: v1.0.1
|
||||
url: http://dummy.url.com/manifests.git
|
||||
|
@ -47,12 +47,10 @@ type Config struct {
|
||||
Manifests map[string]*Manifest `json:"manifests"`
|
||||
|
||||
// CurrentContext is the name of the context that you would like to use by default
|
||||
CurrentContext string `json:"current-context"`
|
||||
CurrentContext string `json:"currentContext"`
|
||||
|
||||
// Modules Section
|
||||
// Will store configuration required by the different airshipctl modules
|
||||
// Such as Bootstrap, Workflows, Document, etc
|
||||
ModulesConfig *Modules `json:"modules-config"`
|
||||
// BootstrapInfo is the configuration for container runtime, ISO builder and remote management
|
||||
BootstrapInfo map[string]*Bootstrap `json:"bootstrapInfo"`
|
||||
|
||||
// loadedConfigPath is the full path to the the location of the config
|
||||
// file from which this config was loaded
|
||||
@ -71,34 +69,26 @@ type Config struct {
|
||||
// ClusterPurpose encapsulates the Cluster Type as an enumeration
|
||||
type ClusterPurpose struct {
|
||||
// Cluster map of referenceable names to cluster configs
|
||||
ClusterTypes map[string]*Cluster `json:"cluster-type"`
|
||||
ClusterTypes map[string]*Cluster `json:"clusterType"`
|
||||
}
|
||||
|
||||
// Cluster contains information about how to communicate with a kubernetes cluster
|
||||
type Cluster struct {
|
||||
// Complex cluster name defined by the using <cluster name>_<cluster type>)
|
||||
NameInKubeconf string `json:"cluster-kubeconf"`
|
||||
NameInKubeconf string `json:"clusterKubeconf"`
|
||||
|
||||
// KubeConfig Cluster Object
|
||||
cluster *kubeconfig.Cluster
|
||||
|
||||
// Bootstrap configuration this clusters ephemeral hosts will rely on
|
||||
Bootstrap string `json:"bootstrap-info"`
|
||||
}
|
||||
|
||||
// Modules encapsulates all module configurations
|
||||
// Configuration that the Bootstrap Module would need
|
||||
// Configuration that the Document Module would need
|
||||
// Configuration that the Workflows Module would need
|
||||
type Modules struct {
|
||||
BootstrapInfo map[string]*Bootstrap `json:"bootstrapInfo"`
|
||||
Bootstrap string `json:"bootstrapInfo"`
|
||||
}
|
||||
|
||||
// Context is a tuple of references to a cluster (how do I communicate with a kubernetes context),
|
||||
// a user (how do I identify myself), and a namespace (what subset of resources do I want to work with)
|
||||
type Context struct {
|
||||
// Context name in kubeconf
|
||||
NameInKubeconf string `json:"context-kubeconf"`
|
||||
NameInKubeconf string `json:"contextKubeconf"`
|
||||
|
||||
// Manifest is the default manifest to be use with this context
|
||||
// +optional
|
||||
@ -118,18 +108,18 @@ type AuthInfo struct {
|
||||
type Manifest struct {
|
||||
// PrimaryRepositoryName is a name of the repo, that contains site/<site-name> directory
|
||||
// and is a starting point for building document bundle
|
||||
PrimaryRepositoryName string `json:"primary-repository-name"`
|
||||
PrimaryRepositoryName string `json:"primaryRepositoryName"`
|
||||
// ExtraRepositories is the map of extra repositories addressable by a name
|
||||
Repositories map[string]*Repository `json:"repositories,omitempty"`
|
||||
// TargetPath Local Target path for working or home dirctory for all Manifest Cloned/Returned/Generated
|
||||
TargetPath string `json:"target-path"`
|
||||
TargetPath string `json:"targetPath"`
|
||||
// SubPath is a path relative to TargetPath + Path where PrimaryRepository is cloned and contains
|
||||
// directories with ClusterType and Phase bundles, example:
|
||||
// Repositories[PrimaryRepositoryName].Url = 'https://github.com/airshipit/treasuremap'
|
||||
// SubPath = "manifests"
|
||||
// you would expect that at treasuremap/manifests you would have ephemeral/initinfra and
|
||||
// ephemera/target directories, containing kustomize.yaml.
|
||||
SubPath string `json:"sub-path"`
|
||||
SubPath string `json:"subPath"`
|
||||
}
|
||||
|
||||
// Repository is a tuple that holds the information for the remote sources of manifest yaml documents.
|
||||
@ -150,13 +140,13 @@ type RepoAuth struct {
|
||||
// supported types are "ssh-key", "ssh-pass", "http-basic"
|
||||
Type string `json:"type,omitempty"`
|
||||
//KeyPassword is a password decrypt ssh private key (used with ssh-key auth type)
|
||||
KeyPassword string `json:"key-pass,omitempty"`
|
||||
KeyPassword string `json:"keyPass,omitempty"`
|
||||
// KeyPath is path to private ssh key on disk (used with ssh-key auth type)
|
||||
KeyPath string `json:"ssh-key,omitempty"`
|
||||
KeyPath string `json:"sshKey,omitempty"`
|
||||
//HTTPPassword is password for basic http authentication (used with http-basic auth type)
|
||||
HTTPPassword string `json:"http-pass,omitempty"`
|
||||
HTTPPassword string `json:"httpPass,omitempty"`
|
||||
// SSHPassword is password for ssh password authentication (used with ssh-pass)
|
||||
SSHPassword string `json:"ssh-pass,omitempty"`
|
||||
SSHPassword string `json:"sshPass,omitempty"`
|
||||
// Username to authenticate against git remote (used with any type)
|
||||
Username string `json:"username,omitempty"`
|
||||
}
|
||||
@ -165,7 +155,7 @@ type RepoAuth struct {
|
||||
// Each field is mutually exclusive
|
||||
type RepoCheckout struct {
|
||||
// CommitHash is full hash of the commit that will be used to checkout
|
||||
CommitHash string `json:"commit-hash,omitempty"`
|
||||
CommitHash string `json:"commitHash,omitempty"`
|
||||
// Branch is the branch name to checkout
|
||||
Branch string `json:"branch"`
|
||||
// Tag is the tag name to checkout
|
||||
@ -174,7 +164,7 @@ type RepoCheckout struct {
|
||||
// RemoteRef is used for remote checkouts such as gerrit change requests/github pull request
|
||||
// for example refs/changes/04/691202/5
|
||||
// TODO Add support for fetching remote refs
|
||||
RemoteRef string `json:"remote-ref"`
|
||||
RemoteRef string `json:"remoteRef"`
|
||||
// ForceCheckout is a boolean to indicate whether to use the `--force` option when checking out
|
||||
ForceCheckout bool `json:"force"`
|
||||
}
|
||||
|
@ -27,6 +27,24 @@ func NewConfig() *Config {
|
||||
return &Config{
|
||||
Kind: AirshipConfigKind,
|
||||
APIVersion: AirshipConfigAPIVersion,
|
||||
BootstrapInfo: map[string]*Bootstrap{
|
||||
AirshipDefaultContext: {
|
||||
Container: &Container{
|
||||
Volume: "/srv/iso:/config",
|
||||
Image: AirshipDefaultBootstrapImage,
|
||||
ContainerRuntime: "docker",
|
||||
},
|
||||
Builder: &Builder{
|
||||
UserDataFileName: "user-data",
|
||||
NetworkConfigFileName: "network-config",
|
||||
OutputMetadataFileName: "output-metadata.yaml",
|
||||
},
|
||||
RemoteDirect: &RemoteDirect{
|
||||
RemoteType: AirshipDefaultRemoteType,
|
||||
IsoURL: AirshipDefaultIsoURL,
|
||||
},
|
||||
},
|
||||
},
|
||||
Clusters: make(map[string]*ClusterPurpose),
|
||||
AuthInfos: make(map[string]*AuthInfo),
|
||||
Contexts: map[string]*Context{
|
||||
@ -51,26 +69,6 @@ func NewConfig() *Config {
|
||||
SubPath: AirshipDefaultManifestRepo + "/manifests/site",
|
||||
},
|
||||
},
|
||||
ModulesConfig: &Modules{
|
||||
BootstrapInfo: map[string]*Bootstrap{
|
||||
AirshipDefaultContext: {
|
||||
Container: &Container{
|
||||
Volume: "/srv/iso:/config",
|
||||
Image: AirshipDefaultBootstrapImage,
|
||||
ContainerRuntime: "docker",
|
||||
},
|
||||
Builder: &Builder{
|
||||
UserDataFileName: "user-data",
|
||||
NetworkConfigFileName: "network-config",
|
||||
OutputMetadataFileName: "output-metadata.yaml",
|
||||
},
|
||||
RemoteDirect: &RemoteDirect{
|
||||
RemoteType: AirshipDefaultRemoteType,
|
||||
IsoURL: AirshipDefaultIsoURL,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -101,12 +99,6 @@ func NewAuthInfo() *AuthInfo {
|
||||
return &AuthInfo{}
|
||||
}
|
||||
|
||||
func NewModules() *Modules {
|
||||
return &Modules{
|
||||
BootstrapInfo: make(map[string]*Bootstrap),
|
||||
}
|
||||
}
|
||||
|
||||
// NewClusterPurpose is a convenience function that returns a new ClusterPurpose
|
||||
func NewClusterPurpose() *ClusterPurpose {
|
||||
return &ClusterPurpose{
|
||||
|
@ -1,34 +1,5 @@
|
||||
apiVersion: airshipit.org/v1alpha1
|
||||
clusters:
|
||||
dummycluster:
|
||||
cluster-type:
|
||||
ephemeral:
|
||||
bootstrap-info: dummy_bootstrap_config
|
||||
cluster-kubeconf: dummycluster_ephemeral
|
||||
contexts:
|
||||
dummy_cluster:
|
||||
context-kubeconf: dummy_cluster
|
||||
manifest: dummy_manifest
|
||||
current-context: dummy_cluster
|
||||
kind: Config
|
||||
manifests:
|
||||
dummy_manifest:
|
||||
primary-repository-name: primary
|
||||
repositories:
|
||||
primary:
|
||||
checkout:
|
||||
branch: "master"
|
||||
force: false
|
||||
remote-ref: ""
|
||||
tag: ""
|
||||
url: {{ airship_config_primary_repo_url }}
|
||||
## this is temporary hack, as soon as we use `document pull` command in gate process
|
||||
## this will subpath will be airshipctl/manifests/site/test-bootstrap, as airshipctl
|
||||
## will be primary repository
|
||||
sub-path: {{ airship_site_name }}
|
||||
target-path: {{ airship_config_manifest_directory }}
|
||||
modules-config:
|
||||
bootstrapInfo:
|
||||
bootstrapInfo:
|
||||
dummy_bootstrap_config:
|
||||
container:
|
||||
volume: {{ airship_config_iso_gen_target_path }}:/config
|
||||
@ -43,5 +14,33 @@ modules-config:
|
||||
userDataFileName: user-data
|
||||
networkConfigFileName: network-config
|
||||
outputMetadataFileName: output-metadata.yaml
|
||||
clusters:
|
||||
dummycluster:
|
||||
clusterType:
|
||||
ephemeral:
|
||||
bootstrapInfo: dummy_bootstrap_config
|
||||
clusterKubeconf: dummycluster_ephemeral
|
||||
contexts:
|
||||
dummy_cluster:
|
||||
contextKubeconf: dummy_cluster
|
||||
manifest: dummy_manifest
|
||||
currentContext: dummy_cluster
|
||||
kind: Config
|
||||
manifests:
|
||||
dummy_manifest:
|
||||
primaryRepositoryName: primary
|
||||
repositories:
|
||||
primary:
|
||||
checkout:
|
||||
branch: "master"
|
||||
force: false
|
||||
remoteRef: ""
|
||||
tag: ""
|
||||
url: {{ airship_config_primary_repo_url }}
|
||||
## this is temporary hack, as soon as we use `document pull` command in gate process
|
||||
## this will subpath will be airshipctl/manifests/site/test-bootstrap, as airshipctl
|
||||
## will be primary repository
|
||||
subPath: {{ airship_site_name }}
|
||||
targetPath: {{ airship_config_manifest_directory }}
|
||||
users:
|
||||
dummy_user: {}
|
||||
|
53
testdata/k8s/config.yaml
vendored
53
testdata/k8s/config.yaml
vendored
@ -1,31 +1,5 @@
|
||||
apiVersion: airshipit.org/v1alpha1
|
||||
clusters:
|
||||
default:
|
||||
cluster-type:
|
||||
target:
|
||||
bootstrap-info: ""
|
||||
cluster-kubeconf: default_target
|
||||
kubernetes:
|
||||
cluster-type: {}
|
||||
contexts:
|
||||
default:
|
||||
context-kubeconf: default_target
|
||||
manifest: default
|
||||
current-context: ""
|
||||
kind: Config
|
||||
manifests:
|
||||
default:
|
||||
repository:
|
||||
checkout:
|
||||
branch: master
|
||||
commit-hash: master
|
||||
force: false
|
||||
remote-ref: master
|
||||
tag: ""
|
||||
url: https://opendev.org/airship/treasuremap
|
||||
target-path: /tmp/default
|
||||
modules-config:
|
||||
bootstrapInfo:
|
||||
bootstrapInfo:
|
||||
default:
|
||||
builder:
|
||||
networkConfigFileName: network-config
|
||||
@ -38,5 +12,30 @@ modules-config:
|
||||
remoteDirect:
|
||||
isoUrl: http://localhost:8099/debian-custom.iso
|
||||
remoteType: redfish
|
||||
clusters:
|
||||
default:
|
||||
clusterType:
|
||||
target:
|
||||
bootstrapInfo: ""
|
||||
clusterKubeconf: default_target
|
||||
kubernetes:
|
||||
clusterType: {}
|
||||
contexts:
|
||||
default:
|
||||
contextKubeconf: default_target
|
||||
manifest: default
|
||||
currentContext: ""
|
||||
kind: Config
|
||||
manifests:
|
||||
default:
|
||||
repository:
|
||||
checkout:
|
||||
branch: master
|
||||
commitHash: master
|
||||
force: false
|
||||
remoteRef: master
|
||||
tag: ""
|
||||
url: https://opendev.org/airship/treasuremap
|
||||
targetPath: /tmp/default
|
||||
users:
|
||||
admin: {}
|
||||
|
@ -47,7 +47,9 @@ func DummyConfig() *config.Config {
|
||||
Manifests: map[string]*config.Manifest{
|
||||
"dummy_manifest": DummyManifest(),
|
||||
},
|
||||
ModulesConfig: DummyModules(),
|
||||
BootstrapInfo: map[string]*config.Bootstrap{
|
||||
"dummy_bootstrap_config": DummyBootstrapInfo(),
|
||||
},
|
||||
CurrentContext: "dummy_context",
|
||||
}
|
||||
conf.SetKubeConfig(kubeconfig.NewConfig())
|
||||
@ -154,13 +156,6 @@ func DummyKubeAuthInfo() *kubeconfig.AuthInfo {
|
||||
return authinfo
|
||||
}
|
||||
|
||||
// DummyModules returns Modules config objects for unit testing
|
||||
func DummyModules() *config.Modules {
|
||||
m := config.NewModules()
|
||||
m.BootstrapInfo["dummy_bootstrap_config"] = DummyBootstrap()
|
||||
return m
|
||||
}
|
||||
|
||||
// DummyClusterPurpose creates ClusterPurpose config object for unit testing
|
||||
func DummyClusterPurpose() *config.ClusterPurpose {
|
||||
cp := config.NewClusterPurpose()
|
||||
@ -234,8 +229,7 @@ func DummyAuthInfoOptions() *config.AuthInfoOptions {
|
||||
return authinfo
|
||||
}
|
||||
|
||||
// DummyBootstrap creates Bootstrap config object for unit testing
|
||||
func DummyBootstrap() *config.Bootstrap {
|
||||
func DummyBootstrapInfo() *config.Bootstrap {
|
||||
bs := &config.Bootstrap{}
|
||||
cont := config.Container{
|
||||
Volume: "/dummy:dummy",
|
||||
@ -256,43 +250,43 @@ func DummyBootstrap() *config.Bootstrap {
|
||||
|
||||
const (
|
||||
testConfigYAML = `apiVersion: airshipit.org/v1alpha1
|
||||
bootstrapInfo:
|
||||
default: {}
|
||||
clusters:
|
||||
straggler:
|
||||
cluster-type:
|
||||
clusterType:
|
||||
ephemeral:
|
||||
cluster-kubeconf: notThere
|
||||
clusterKubeconf: notThere
|
||||
def:
|
||||
cluster-type:
|
||||
clusterType:
|
||||
ephemeral:
|
||||
bootstrap-info: ""
|
||||
cluster-kubeconf: def_ephemeral
|
||||
bootstrapInfo: ""
|
||||
clusterKubeconf: def_ephemeral
|
||||
target:
|
||||
bootstrap-info: ""
|
||||
cluster-kubeconf: def_target
|
||||
bootstrapInfo: ""
|
||||
clusterKubeconf: def_target
|
||||
onlyinkubeconf:
|
||||
cluster-type:
|
||||
clusterType:
|
||||
target:
|
||||
bootstrap-info: ""
|
||||
cluster-kubeconf: onlyinkubeconf_target
|
||||
bootstrapInfo: ""
|
||||
clusterKubeconf: onlyinkubeconf_target
|
||||
wrongonlyinconfig:
|
||||
cluster-type: {}
|
||||
clusterType: {}
|
||||
wrongonlyinkubeconf:
|
||||
cluster-type:
|
||||
clusterType:
|
||||
target:
|
||||
bootstrap-info: ""
|
||||
cluster-kubeconf: wrongonlyinkubeconf_target
|
||||
bootstrapInfo: ""
|
||||
clusterKubeconf: wrongonlyinkubeconf_target
|
||||
contexts:
|
||||
def_ephemeral:
|
||||
context-kubeconf: def_ephemeral
|
||||
contextKubeconf: def_ephemeral
|
||||
def_target:
|
||||
context-kubeconf: def_target
|
||||
contextKubeconf: def_target
|
||||
onlyink:
|
||||
context-kubeconf: onlyinkubeconf_target
|
||||
current-context: ""
|
||||
contextKubeconf: onlyinkubeconf_target
|
||||
currentContext: ""
|
||||
kind: Config
|
||||
manifests: {}
|
||||
modules-config:
|
||||
dummy-for-tests: ""
|
||||
users:
|
||||
k-admin: {}
|
||||
k-other: {}
|
||||
|
Loading…
Reference in New Issue
Block a user