Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
noc
tower
Commits
c80bb4c0
Commit
c80bb4c0
authored
Aug 31, 2017
by
Dmitry Volodin
Browse files
St. Marco's Campanile branch: golang core implementation
parent
c2275117
Pipeline
#1795
passed with stage
in 41 seconds
Changes
16
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
.gitignore
View file @
c80bb4c0
.idea/*
noc_tower.egg-info/
build/
dist/
root/
.*
!.gitlab-ci.yml
!.gitignore
!.dockerignore
bin/
pkg/
var/
pip-selfcheck.json
local/
lib/
include/
bin/*
share/
*.pyc
.idea/
\ No newline at end of file
core/src/tower/vendor/*
core/src/github.com/
!core/src/tower/vendor/manifest
core/src/tower/command/command.go
0 → 100644
View file @
c80bb4c0
//----------------------------------------------------------------------
// Commands entrypoint
//----------------------------------------------------------------------
// Copyright (C) 2017
//----------------------------------------------------------------------
package
command
import
(
"errors"
)
type
CommandInterface
interface
{
GetName
()
string
GetShort
()
string
Run
()
int
SetParser
()
}
type
Command
struct
{
name
string
short
string
}
func
(
c
Command
)
GetName
()
string
{
return
c
.
name
}
func
(
c
Command
)
GetShort
()
string
{
return
c
.
short
}
func
(
c
Command
)
Run
()
int
{
return
0
}
func
(
c
Command
)
SetParser
()
{
}
func
FindCmd
(
name
string
)
(
CommandInterface
,
error
)
{
for
_
,
c
:=
range
CommandsList
{
if
c
.
GetName
()
==
name
{
return
c
,
nil
}
}
return
nil
,
errors
.
New
(
"Invalid command"
)
}
var
CommandsList
=
[]
CommandInterface
{
cmdHelp
,
cmdVersion
,
cmdDump
,
cmdCommit
,
}
core/src/tower/command/commit.go
0 → 100644
View file @
c80bb4c0
//----------------------------------------------------------------------
// tower commit
//----------------------------------------------------------------------
// Copyright (C) 2017, The NOC Project
//----------------------------------------------------------------------
package
command
import
(
"flag"
"fmt"
"tower/config"
)
type
CommitCommand
struct
{
Command
}
var
cmdCommit
=
CommitCommand
{
Command
{
"commit"
,
"Commit configuration from file"
,
},
}
var
commit_file
*
string
func
(
c
CommitCommand
)
SetParser
()
{
commit_file
=
flag
.
String
(
"file"
,
""
,
"Config file path"
)
}
func
(
c
CommitCommand
)
Run
()
int
{
if
*
commit_file
==
""
{
fmt
.
Printf
(
"File path required
\n
"
)
return
1
}
cfg
,
err
:=
config
.
ParseFile
(
*
commit_file
)
if
err
!=
nil
{
fmt
.
Printf
(
"Cannot read file '%s': %s
\n
"
,
*
commit_file
,
err
)
return
1
}
fmt
.
Printf
(
"CONFIG=%+v
\n
"
,
cfg
)
return
0
}
core/src/tower/command/dump.go
0 → 100644
View file @
c80bb4c0
//----------------------------------------------------------------------
// tower dump
//----------------------------------------------------------------------
// Copyright (C) 2017, The NOC Project
//----------------------------------------------------------------------
package
command
import
(
"fmt"
)
type
DumpCommand
struct
{
Command
}
var
cmdDump
=
DumpCommand
{
Command
{
"dump"
,
"Dump current config"
,
},
}
func
(
c
DumpCommand
)
Run
()
int
{
fmt
.
Println
(
"dump"
)
return
0
}
core/src/tower/command/help.go
0 → 100644
View file @
c80bb4c0
//----------------------------------------------------------------------
// tower help
//----------------------------------------------------------------------
// Copyright (C) 2017, The NOC Project
//----------------------------------------------------------------------
package
command
import
"fmt"
type
HelpCommand
struct
{
Command
}
var
cmdHelp
=
HelpCommand
{
Command
{
name
:
"help"
,
short
:
"help on help"
,
},
}
func
(
c
HelpCommand
)
Run
()
int
{
fmt
.
Println
(
"Usage:"
)
for
_
,
c
:=
range
CommandsList
{
fmt
.
Printf
(
"
\t
%8s - %s
\n
"
,
c
.
GetName
(),
c
.
GetShort
())
}
return
0
}
func
Help
()
{
cmdHelp
.
Run
()
}
core/src/tower/command/version.go
0 → 100644
View file @
c80bb4c0
//----------------------------------------------------------------------
// tower version
//----------------------------------------------------------------------
// Copyright (C) 2017, The NOC Project
//----------------------------------------------------------------------
package
command
import
(
"fmt"
"runtime"
)
const
version
=
"0.1a"
func
GetVersion
()
string
{
return
version
}
type
VersionCommand
struct
{
Command
}
var
cmdVersion
=
VersionCommand
{
Command
{
"version"
,
"help on version"
,
},
}
func
(
c
VersionCommand
)
Run
()
int
{
fmt
.
Printf
(
"tower version %s %s/%s
\n
"
,
GetVersion
(),
runtime
.
GOOS
,
runtime
.
GOARCH
,
)
return
0
}
core/src/tower/config/config.go
0 → 100644
View file @
c80bb4c0
//----------------------------------------------------------------------
// config structure
//----------------------------------------------------------------------
// Copyright (C) 2017, The NOC Project
//----------------------------------------------------------------------
package
config
import
(
"fmt"
"github.com/tylerb/gls"
yaml
"gopkg.in/yaml.v2"
"io/ioutil"
"os"
)
const
(
CURRENT_VERSION
=
FMT_V1
CONFIG_KEY
=
"cfg"
)
type
Config
struct
{
Version
string
Templates
[]
Template
`yaml:,flow`
Pools
[]
Pool
`yaml:,flow`
Roles
[]
Role
`yaml:,flow`
Datacenters
[]
Datacenter
`yaml:,flow`
Hosts
[]
Host
`yaml:,flow`
Services
[]
Service
`yaml:,flow`
}
func
Parse
(
data
[]
byte
)
(
*
Config
,
error
)
{
// Check config format Version
version
,
err
:=
GetConfigFormatVersion
(
data
)
if
err
!=
nil
{
return
nil
,
err
}
// Parse only current Version
// @todo: Legacy versions conversion
if
version
!=
CURRENT_VERSION
{
return
nil
,
fmt
.
Errorf
(
"Expected Version '%s"
,
CURRENT_VERSION
)
}
// Parse config
// Pass gls context to unmarshal to use in local parsers
config
:=
Config
{}
gls
.
With
(
gls
.
Values
{
CONFIG_KEY
:
&
config
},
func
()
{
err
=
yaml
.
Unmarshal
(
data
,
&
config
)
})
if
err
!=
nil
{
return
nil
,
err
}
// @todo: Additional validation
return
&
config
,
nil
}
func
ParseFile
(
path
string
)
(
*
Config
,
error
)
{
file
,
err
:=
os
.
Open
(
path
)
if
err
!=
nil
{
return
nil
,
err
}
defer
file
.
Close
()
data
,
err
:=
ioutil
.
ReadAll
(
file
)
if
err
!=
nil
{
return
nil
,
err
}
return
Parse
(
data
)
}
func
(
c
*
Config
)
GetPoolByName
(
name
string
)
*
Pool
{
for
i
:=
range
c
.
Pools
{
if
c
.
Pools
[
i
]
.
Name
==
name
{
return
&
c
.
Pools
[
i
]
}
}
return
nil
}
func
(
c
*
Config
)
GetRoleByName
(
name
string
)
*
Role
{
for
i
:=
range
c
.
Roles
{
if
c
.
Roles
[
i
]
.
Name
==
name
{
return
&
c
.
Roles
[
i
]
}
}
return
nil
}
func
(
c
*
Config
)
GetDatacenterByName
(
name
string
)
*
Datacenter
{
for
i
:=
range
c
.
Datacenters
{
if
c
.
Datacenters
[
i
]
.
Name
==
name
{
return
&
c
.
Datacenters
[
i
]
}
}
return
nil
}
func
(
c
*
Config
)
GetTemplateByName
(
name
string
)
*
Template
{
for
i
:=
range
c
.
Templates
{
if
c
.
Templates
[
i
]
.
Name
==
name
{
return
&
c
.
Templates
[
i
]
}
}
return
nil
}
func
(
c
*
Config
)
GetHostByName
(
name
string
)
*
Host
{
for
i
:=
range
c
.
Hosts
{
if
c
.
Hosts
[
i
]
.
Name
==
name
{
return
&
c
.
Hosts
[
i
]
}
}
return
nil
}
//
// Parse array of strings as array of template references
//
func
(
c
*
Config
)
ParseTemplates
(
templates
[]
string
)
([]
*
Template
,
error
)
{
result
:=
[]
*
Template
{}
for
i
:=
range
templates
{
tpl
:=
c
.
GetTemplateByName
(
templates
[
i
])
if
tpl
==
nil
{
return
nil
,
fmt
.
Errorf
(
"Invalid template '%s'"
,
templates
[
i
])
}
result
=
append
(
result
,
tpl
)
}
return
result
,
nil
}
//
// Parse array of strings as array of roles references
//
func
(
c
*
Config
)
ParseRoles
(
roles
[]
string
)
([]
*
Role
,
error
)
{
result
:=
[]
*
Role
{}
for
i
:=
range
roles
{
tpl
:=
c
.
GetRoleByName
(
roles
[
i
])
if
tpl
==
nil
{
return
nil
,
fmt
.
Errorf
(
"Invalid role '%s'"
,
roles
[
i
])
}
result
=
append
(
result
,
tpl
)
}
return
result
,
nil
}
core/src/tower/config/datacenter.go
0 → 100644
View file @
c80bb4c0
//----------------------------------------------------------------------
// Datacenter
//----------------------------------------------------------------------
// Copyright (C) 2017, The NOC Project
//----------------------------------------------------------------------
package
config
import
(
"fmt"
"github.com/tylerb/gls"
)
type
Datacenter
struct
{
Name
string
Description
string
Templates
[]
*
Template
}
func
(
c
*
Datacenter
)
UnmarshalYAML
(
unmarshal
func
(
interface
{})
error
)
error
{
// Auxiliary structure
var
aux
struct
{
Name
string
Description
string
Templates
[]
string
}
err
:=
unmarshal
(
&
aux
)
if
err
!=
nil
{
return
err
}
//
if
aux
.
Name
==
""
{
return
fmt
.
Errorf
(
"Empty datacenter name"
)
}
// Copy structure
c
.
Name
=
aux
.
Name
c
.
Description
=
aux
.
Description
// Parse templates
config
:=
gls
.
Get
(
CONFIG_KEY
)
.
(
*
Config
)
c
.
Templates
,
err
=
config
.
ParseTemplates
(
aux
.
Templates
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"datacenter %s: %s"
,
c
.
Name
,
err
)
}
return
nil
}
core/src/tower/config/host.go
0 → 100644
View file @
c80bb4c0
//----------------------------------------------------------------------
// Host
//----------------------------------------------------------------------
// Copyright (C) 2017, The NOC Project
//----------------------------------------------------------------------
package
config
import
(
"fmt"
"github.com/tylerb/gls"
"strconv"
)
const
(
HT_UNKNOWN
=
0
HT_LINUX
HT_FREEBSD
HT_DOCKER
HT_SWARM
HT_K8S
HT_NOMAD
HT_MESOS
DEFAULT_HOST_PORT
=
22
)
var
HT_MAP
=
map
[
string
]
int
{
"linux"
:
HT_LINUX
,
"freebsd"
:
HT_FREEBSD
,
"docker"
:
HT_DOCKER
,
"swarm"
:
HT_SWARM
,
"kubernetes"
:
HT_K8S
,
"nomad"
:
HT_NOMAD
,
"mesos"
:
HT_MESOS
,
}
type
Host
struct
{
Name
string
Description
string
Type
int
Address
string
Port
int
User
string
Password
string
Datacenter
*
Datacenter
Roles
[]
*
Role
Templates
[]
*
Template
}
func
(
c
*
Host
)
UnmarshalYAML
(
unmarshal
func
(
interface
{})
error
)
error
{
// Auxiliary structure
var
aux
struct
{
Name
string
Description
string
Type
string
Address
string
Port
string
User
string
Password
string
Datacenter
string
Roles
[]
string
Templates
[]
string
}
var
port
int
err
:=
unmarshal
(
&
aux
)
if
err
!=
nil
{
return
err
}
//
if
aux
.
Name
==
""
{
return
fmt
.
Errorf
(
"Empty host name"
)
}
// Check port
if
aux
.
Port
==
""
{
port
=
DEFAULT_HOST_PORT
}
else
{
port
,
err
=
strconv
.
Atoi
(
aux
.
Port
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"host %s: Invalid port '%s'"
,
aux
.
Name
,
aux
.
Port
)
}
}
// Check type
htype
,
ok
:=
HT_MAP
[
aux
.
Type
]
if
!
ok
{
return
fmt
.
Errorf
(
"host %s: Invalid host type '%s'"
,
aux
.
Name
,
aux
.
Type
)
}
// Dereference datacenter
if
aux
.
Datacenter
==
""
{
return
fmt
.
Errorf
(
"host %s: Empty datacenter"
,
aux
.
Name
)
}
config
:=
gls
.
Get
(
CONFIG_KEY
)
.
(
*
Config
)
// Copy structure
c
.
Name
=
aux
.
Name
c
.
Description
=
aux
.
Description
c
.
Type
=
htype
c
.
Address
=
aux
.
Address
c
.
Port
=
port
c
.
User
=
aux
.
User
c
.
Password
=
aux
.
Password
// Get datacenter
c
.
Datacenter
=
config
.
GetDatacenterByName
(
aux
.
Datacenter
)
if
c
.
Datacenter
==
nil
{
return
fmt
.
Errorf
(
"host %s: Invalid datacenter '%s'"
,
aux
.
Name
,
aux
.
Datacenter
)
}
// Parse roles
c
.
Roles
,
err
=
config
.
ParseRoles
(
aux
.
Roles
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"datacenter %s: %s"
,
c
.
Name
,
err
)
}
// Parse templates
c
.
Templates
,
err
=
config
.
ParseTemplates
(
aux
.
Templates
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"datacenter %s: %s"
,
c
.
Name
,
err
)
}
return
nil
}
core/src/tower/config/pool.go
0 → 100644
View file @
c80bb4c0
//----------------------------------------------------------------------
// Pool
//----------------------------------------------------------------------
// Copyright (C) 2017, The NOC Project
//----------------------------------------------------------------------
package
config
import
(
"fmt"
"github.com/tylerb/gls"
"regexp"
)
type
Pool
struct
{
Name
string
Description
string
Templates
[]
*
Template
}
var
rx_pool_name
*
regexp
.
Regexp
func
(
c
*
Pool
)
UnmarshalYAML
(
unmarshal
func
(
interface
{})
error
)
error
{
// Auxiliary structure
var
aux
struct
{
Name
string
Description
string
Templates
[]
string
}
err
:=
unmarshal
(
&
aux
)
if
err
!=
nil
{
return
err
}
//
if
aux
.
Name
==
""
{
return
fmt
.
Errorf
(
"Empty pool name"
)
}
// Check name format
matched
:=
rx_pool_name
.
Match
([]
byte
(
aux
.
Name
))
if
!
matched
{
return
fmt
.
Errorf
(
"Invalid pool name: '%s'"
,
aux
.
Name
)
}
// Copy structure
c
.
Name
=
aux
.
Name
c
.
Description
=
aux
.
Description
// Parse templates
config
:=
gls
.
Get
(
CONFIG_KEY
)
.
(
*
Config
)
c
.
Templates
,
err
=
config
.
ParseTemplates
(
aux
.
Templates
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"datacenter %s: %s"
,
c
.
Name
,
err
)
}
return
nil
}
func
init
()
{
rx_pool_name
,
_
=
regexp
.
Compile
(
"^[a-zA-Z][a-zA-Z0-9]*$"
)
}
core/src/tower/config/role.go
0 → 100644
View file @
c80bb4c0
//----------------------------------------------------------------------
// Role
//----------------------------------------------------------------------
// Copyright (C) 2017, The NOC Project
//----------------------------------------------------------------------
package
config
import
(
"fmt"
"net/url"
)
type
Role
struct
{
Name
string
Description
string
Url
string
}
func
(
c
*
Role
)
UnmarshalYAML
(
unmarshal
func
(
interface
{})
error
)
error
{
// Auxiliary structure
var
aux
struct
{
Name
string
Description
string
Url
string
}
err
:=
unmarshal
(
&
aux
)
if
err
!=
nil
{
return
err
}
// Check required parameters
if
aux
.
Name
==
""
{
return
fmt
.
Errorf
(
"Empty role name"
)
}
if
aux
.
Url
==
""
{
return
fmt
.
Errorf
(
"Empty URL for role '%s'"
,
aux
.
Name
)