Fleshed out how projects will be loaded and run
Started on datastores
This commit is contained in:
parent
8475ac6049
commit
cb883bc528
2
LICENSE
2
LICENSE
@ -1,5 +1,5 @@
|
|||||||
MIT License
|
MIT License
|
||||||
Copyright (c) <year> <copyright holders>
|
Copyright (c) 2016 Tim Shannon
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
6
datastore/ds.go
Normal file
6
datastore/ds.go
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
// Copyright 2016 Tim Shannon. All rights reserved.
|
||||||
|
// Use of this source code is governed by the MIT license
|
||||||
|
// that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package datastore manages the bolt data files and the reading and writing data to them
|
||||||
|
package datastore
|
16
main.go
16
main.go
@ -1,3 +1,7 @@
|
|||||||
|
// Copyright 2016 Tim Shannon. All rights reserved.
|
||||||
|
// Use of this source code is governed by the MIT license
|
||||||
|
// that can be found in the LICENSE file.
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -10,8 +14,8 @@ import (
|
|||||||
|
|
||||||
//settings
|
//settings
|
||||||
var (
|
var (
|
||||||
projectDir = "./projects" // /etc/
|
projectDir = "./projects" // /etc/ironsmith/
|
||||||
dataDir = "./data"
|
dataDir = "./data" // /var/ironsmith/
|
||||||
address = "http://localhost:8026"
|
address = "http://localhost:8026"
|
||||||
certFile = ""
|
certFile = ""
|
||||||
keyFile = ""
|
keyFile = ""
|
||||||
@ -37,12 +41,12 @@ func main() {
|
|||||||
keyFile = cfg.String("keyFile", keyFile)
|
keyFile = cfg.String("keyFile", keyFile)
|
||||||
|
|
||||||
//prep dirs
|
//prep dirs
|
||||||
err = os.MkdirAll(filepath.Join(projectDir, enabledProjectDir), os.ModeDir)
|
err = os.MkdirAll(filepath.Join(projectDir, enabledProjectDir), 0777)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error Creating project directory at %s: %s", projectDir, err)
|
log.Fatalf("Error Creating project directory at %s: %s", projectDir, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = os.MkdirAll(dataDir, os.ModeDir)
|
err = os.MkdirAll(dataDir, 0777)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error Creating project data directory at %s: %s", dataDir, err)
|
log.Fatalf("Error Creating project data directory at %s: %s", dataDir, err)
|
||||||
}
|
}
|
||||||
@ -53,5 +57,9 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//load projects
|
//load projects
|
||||||
|
err = projects.load()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Error loading projects: %s", err)
|
||||||
|
}
|
||||||
//start server
|
//start server
|
||||||
}
|
}
|
||||||
|
135
project.go
135
project.go
@ -1,14 +1,31 @@
|
|||||||
|
// Copyright 2016 Tim Shannon. All rights reserved.
|
||||||
|
// Use of this source code is governed by the MIT license
|
||||||
|
// that can be found in the LICENSE file.
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const enabledProjectDir = "enabled"
|
const enabledProjectDir = "enabled"
|
||||||
|
|
||||||
// Project is an ironsmith project that contains how to fetch, build, test, and release a project
|
// Project is an ironsmith project that contains how to fetch, build, test, and release a project
|
||||||
|
/*
|
||||||
|
The project lifecycle goes like this, each step calling the next if successful
|
||||||
|
(Load Project file) -> (Fetch) -> (Build) -> (Test) -> (Release) - > (Sleep for polling period) ->
|
||||||
|
(Reload Project File) -> (Fetch) -> etc...
|
||||||
|
|
||||||
|
Changes the project file will be reloaded on every poll / trigger
|
||||||
|
If a project file is deleted then the cycle will finish it's current poll and stop at the load phase
|
||||||
|
*/
|
||||||
type Project struct {
|
type Project struct {
|
||||||
Name string `json:"name"` // name of the project
|
Name string `json:"name"` // name of the project
|
||||||
|
|
||||||
@ -22,6 +39,9 @@ type Project struct {
|
|||||||
ReleaseFile string `json:"releaseFile"`
|
ReleaseFile string `json:"releaseFile"`
|
||||||
PollInterval string `json:"pollInterval"` // if not poll interval is specified, this project is trigger only
|
PollInterval string `json:"pollInterval"` // if not poll interval is specified, this project is trigger only
|
||||||
TriggerSecret string `json:"triggerSecret"` //secret to be included with a trigger call
|
TriggerSecret string `json:"triggerSecret"` //secret to be included with a trigger call
|
||||||
|
|
||||||
|
filename string
|
||||||
|
poll time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
const projectTemplateFilename = "template.project.json"
|
const projectTemplateFilename = "template.project.json"
|
||||||
@ -69,3 +89,118 @@ func prepTemplateProject() error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Project) load() error {
|
||||||
|
if p.filename == "" {
|
||||||
|
return fmt.Errorf("Invalid project file name")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !projects.exists(p.filename) {
|
||||||
|
// project has been deleted
|
||||||
|
// don't continue polling
|
||||||
|
// TODO: Clean up Project data folder?
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := ioutil.ReadFile(filepath.Join(projectDir, enabledProjectDir, p.filename))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = json.Unmarshal(data, p)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = p.prepData()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.PollInterval != "" {
|
||||||
|
p.poll, err = time.ParseDuration(p.PollInterval)
|
||||||
|
if err != nil {
|
||||||
|
//TODO: Log pollInterval parse failure in project store
|
||||||
|
p.poll = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.poll > 0 {
|
||||||
|
//start polling
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// prepData makes sure the project's data folder and data store is created
|
||||||
|
/*
|
||||||
|
folder structure
|
||||||
|
projectDataFolder/<project-name>/<project-version>
|
||||||
|
|
||||||
|
*/
|
||||||
|
func (p *Project) prepData() error {
|
||||||
|
var dirName = strings.TrimSuffix(p.filename, filepath.Ext(p.filename))
|
||||||
|
err := os.MkdirAll(filepath.Join(dataDir, dirName), 0777)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: Create data store
|
||||||
|
}
|
||||||
|
|
||||||
|
type projectList struct {
|
||||||
|
sync.RWMutex
|
||||||
|
data map[string]*Project
|
||||||
|
}
|
||||||
|
|
||||||
|
var projects = projectList{
|
||||||
|
data: make(map[string]*Project),
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *projectList) load() error {
|
||||||
|
p.Lock()
|
||||||
|
defer p.Unlock()
|
||||||
|
|
||||||
|
dir, err := os.Open(filepath.Join(projectDir, enabledProjectDir))
|
||||||
|
defer func() {
|
||||||
|
if cerr := dir.Close(); cerr != nil && err == nil {
|
||||||
|
err = cerr
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
files, err := dir.Readdir(0)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range files {
|
||||||
|
if !files[i].IsDir() && filepath.Ext(files[i].Name()) == ".json" {
|
||||||
|
prj := &Project{filename: files[i].Name()}
|
||||||
|
p.data[files[i].Name()] = prj
|
||||||
|
|
||||||
|
err = prj.load()
|
||||||
|
if err != nil {
|
||||||
|
delete(p, files[i].Name())
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *projectList) exists(name string) bool {
|
||||||
|
p.RLock()
|
||||||
|
defer p.RUnlock()
|
||||||
|
|
||||||
|
_, ok := p.data[name]
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// startProjectLoader polls for new projects
|
||||||
|
func startProjectLoader() {
|
||||||
|
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user