Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resolve issues #28,#29,#30 #32

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
1 change: 1 addition & 0 deletions auth/auth.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Package auth access
package auth

import (
Expand Down
1 change: 1 addition & 0 deletions client/client.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Package client access
package client

import (
Expand Down
7 changes: 6 additions & 1 deletion cmd/goatOs.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Package cmd access
package cmd

import (
Expand Down Expand Up @@ -33,7 +34,8 @@ var goatOsFlags = []string{constants.CfgIdentifier, constants.CfgRecordsFrom, co
constants.CfgScopeProjectName, constants.CfgScopeDomainID, constants.CfgScopeDomainName, constants.CfgScopeSystem,
constants.CfgAppCredentialID, constants.CfgAppCredentialName, constants.CfgAppCredentialSecret,
constants.CfgEndpointType, constants.CfgEndpointName, constants.CfgEndpointRegion,
constants.CfgEndpointAvailability, constants.CfgDebug, constants.CfgLogPath}
constants.CfgEndpointAvailability, constants.CfgDebug, constants.CfgLogPath,
constants.CfgTags, constants.CfgIgnoreTags, constants.CfgDefaultTag}

var goatOsRequired = []string{constants.CfgIdentifier, constants.CfgGoatEndpoint,
constants.CfgOpenstackIdentityEndpoint}
Expand All @@ -43,6 +45,9 @@ var goatOsDescription = map[string]string{
constants.CfgRecordsFrom: "records from [TIME]",
constants.CfgRecordsTo: "records to [TIME]",
constants.CfgRecordsForPeriod: "records for period [TIME PERIOD]",
constants.CfgTags: "projects with specified [TAG]",
constants.CfgIgnoreTags: "projects with any [TAG]",
constants.CfgDefaultTag: "specifies the default [TAG]",

constants.CfgGoatEndpoint: "goat server [GOAT_SERVER_ENDPOINT] (required)",
constants.CfgOpenstackIdentityEndpoint: "Openstack identity endpoint [OS_IDENTITY_ENDPOINT] (required)",
Expand Down
49 changes: 31 additions & 18 deletions config/goat-os.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@ records-from:
# time format: yyyy-mm-dd hh:mm:ss + nsec nanoseconds
records-to:

# Ignores tags when filtering projects
ignore-tags: true

# Specifies the default tag which is used to determine projects to use
default-tag: caso


# Records for given period (optional)
# The following tokens may be used to specify the respective unit of time:
# Nanosecond: ns
Expand All @@ -38,27 +45,32 @@ records-for-period:

# Goat server endpoint (required)
endpoint: 127.0.0.1:9623
# endpoint: 78.128.250.28:9623

# Openstack identity endpoint (required)
openstack-identity-endpoint: https://openstack.example.com:5000/v3
# openstack-identity-endpoint: https://openstack.example.com:5000/v3
openstack-identity-endpoint: https://identity.cloud.muni.cz/v3


# Auth-options stores information needed to authenticate to
# an OpenStack Cloud. (required)
auth-options:
# Username is required if using Identity V2 API.
# In Identity V3, either user-id or a combination of username and
# domain-id or domain-name are needed.
username:
user-id:
password:
# Put either username or user-id, not both.
username:
user-id:
password:

# Passcode is used in TOTP authentication method.
passcode:

# At most one of domain-id and domain-name must be provided if using
# username with Identity V3. Otherwise, either are optional.
# Don't provide domain-name if you used user-id.
domain-id:
domain-name:
domain-name:

# The tenant-id and tenant-name fields are optional for the Identity V2 API.
# The same fields are known as project-id and project-name in the Identity
Expand All @@ -72,32 +84,33 @@ auth-options:
# accomplish that, the project-id will need to be provided as the tenant-id
# option.
tenant-id:
tenant-name:
tenant-name:

# Allow-reauth should be set to true if you grant permission for developers to
# cache your credentials in memory, and to allow developers to attempt to
# re-authenticate automatically if/when your token expires. If you set it to
# false, it will not cache these settings, but re-authentication will not be
# possible. This setting defaults to false.
allow-reauth:
allow-reauth: true

# Token-id allows users to authenticate (possibly as another user) with an
# authentication token ID.
token-id:
token-id: gAAAAABlEsN38cByrKuajByJItEEsxcikpIWcr0O4ILeDidCqdLpPtJPpc8D8wk8N1R8FHkcomrlDAYc3PLnc3Hl7FsntvnCBB-B-KS8JU7tIkw_NxMgS6qHt4jOM62BQQCJnHHXkhbfmz7rawP5VO4OzCWVbqtmZTWJyZLlaooXW3zZKmqVWMw

# Scope determines the scoping of the authentication request.
# It allows a created token to be limited to a specific domain or project.
scope-project-id:
# Put either project-id or project-name, not both.
scope-project-id:
scope-project-name:
scope-domain-id:
scope-domain-name:
scope-domain-name: egi_eu
scope-system:

# Authentication through Application Credentials requires supplying name,
# project and secret. For project we can use tenant-id.
application-credential-id:
application-credential-name:
application-credential-secret:
# application-credential-id: 14b01e088ed045358c9a6a963fc45b55
# application-credential-name:
# application-credential-secret: FHOVTMO0iuKTatwYG8_IWRa5sl7WYcifo4xV9eJ1a_w3qOn6CVn1v340kRS71P_ARApM6R8Tv-iQE7rhAfb-4A

# Endpoint options specifies search criteria used by queries against an
# OpenStack service catalog. The options must contain enough information to
Expand All @@ -106,17 +119,17 @@ endpoint-options:
# Type is the service type for the client (e.g., "compute",
# "object-store"). Generally, this will be supplied by the service client
# function, but a user-given value will be honored if provided.
type:
type:

# Name is the service name for the client (e.g., "nova") as it
# appears in the service catalog. Services can have the same Type but a
# different Name, which is why both Type and Name are sometimes needed.
name:
name:

# Region is the geographic region in which the endpoint resides,
# generally specifying which data center should house your resources.
# Required only for services that span multiple regions.
region:
region: brno1

# Availability indicates to whom a specific service endpoint is accessible:
# the internet at large, internal networks only, or only to administrators.
Expand All @@ -129,10 +142,10 @@ endpoint-options:
#
# Availability is not required, and defaults to public. Not all providers or
# services offer all Availability options.
availability:
availability: public

# Debug mode (true/false)
debug: false
debug: true

# Path to log file (optional)
log-path:
Expand Down
1 change: 1 addition & 0 deletions constants/auth.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Package constants access
package constants

// prefix for authentication options
Expand Down
9 changes: 9 additions & 0 deletions constants/global.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,13 @@ const (

// CfgLogPath represents path to log file
CfgLogPath = "log-path"

// CfgTags represents tags
CfgTags = "tags"

// CfgIgnoreTags represents flag for turning off filtering based on tags
CfgIgnoreTags = "ignore-tags"

// CfgDefaultTag represents default value for the tag flag
CfgDefaultTag = "default-tag"
)
1 change: 1 addition & 0 deletions filter/filter.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Package filter access
package filter

import (
Expand Down
1 change: 1 addition & 0 deletions goat-os.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Package main access
package main

import "github.com/goat-project/goat-os/cmd"
Expand Down
1 change: 1 addition & 0 deletions initialize/initialize.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Package initialize access
package initialize

import (
Expand Down
1 change: 1 addition & 0 deletions logger/logger.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Package logger access
package logger

import (
Expand Down
1 change: 1 addition & 0 deletions preparer/interface.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Package preparer access
package preparer

import (
Expand Down
1 change: 1 addition & 0 deletions processor/interface.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Package processor access
package processor

import (
Expand Down
57 changes: 56 additions & 1 deletion processor/processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ package processor
import (
"sync"

"github.com/goat-project/goat-os/constants"
"github.com/goat-project/goat-os/reader"
"github.com/spf13/viper"

"github.com/goat-project/goat-os/auth"
"github.com/gophercloud/gophercloud"
Expand Down Expand Up @@ -33,6 +35,7 @@ func CreateProcessor(proc processorI) *Processor {

// ListProjects lists projects from Openstack to create individual service clients.
func (p *Processor) ListProjects(projChan chan projects.Project) {

availableProjects, err := p.proc.Reader().ListAvailableProjects()
if err != nil {
log.WithFields(log.Fields{"err": err}).Fatal("unable to list available projects")
Expand All @@ -49,7 +52,9 @@ func (p *Processor) ListProjects(projChan chan projects.Project) {
}

for i := range projs {
projChan <- projs[i]
if commonTagExists(getTags(), projs[i].Tags) {
projChan <- projs[i]
}
}

close(projChan)
Expand Down Expand Up @@ -77,3 +82,53 @@ func (p *Processor) ListResources(projChan chan projects.Project, read chan reso
wg.Wait()
close(read)
}

// Util
func getTags() []string {
specifiedTags := []string{viper.GetString(constants.CfgDefaultTag)} // Default state for tags is a default tag

if len(viper.GetStringSlice(constants.CfgTags)) != 0 { // There are some tags specified
specifiedTags = []string{}
specifiedTags = append(specifiedTags, viper.GetStringSlice(constants.CfgTags)...)
}

if viper.GetBool(constants.CfgIgnoreTags) { // Ignoring tags
specifiedTags = []string{}
}
return specifiedTags
}

func isEmpty(arr []string) bool {
return len(arr) == 0
}

func commonTagExists(specifiedTags, serverTags []string) bool {

// Case when tags are ignored
if isEmpty(specifiedTags) {
return true
}

// Case when tags are not ignored but server has no tags
if isEmpty(serverTags) {
return false
}

// Create a map to store unique strings from the first array.
stringMap := make(map[string]bool)

// Populate the map with strings from the first array.
for _, str := range specifiedTags {
stringMap[str] = true
}

// Check if any string from the second array is present in the map.
for _, str := range serverTags {
if stringMap[str] {
return true
}
}

// If no common strings were found, return false.
return false
}
6 changes: 6 additions & 0 deletions reader/reader.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Package reader access
package reader

import (
Expand Down Expand Up @@ -85,6 +86,11 @@ func (r *Reader) GetUser(id string) (result.Result, error) {
return r.readResource(&resource.UserReader{ID: id})
}

// GetProject gets project from Openstack.
func (r *Reader) GetProject(id string) (result.Result, error) {
return r.readResource(&resource.ProjectReader{ID: id})
}

// ListAllFlavors lists all flavors from Openstack.
func (r *Reader) ListAllFlavors() (pagination.Pager, error) {
return r.readResources(&resource.FlavorReader{})
Expand Down
1 change: 1 addition & 0 deletions resource/flavorReader.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Package resource access
package resource

import (
Expand Down
1 change: 1 addition & 0 deletions resource/gpu/filter.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Package gpu access
package gpu

import (
Expand Down
1 change: 1 addition & 0 deletions resource/gpu/reader/reader.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Package reader access
package reader

import (
Expand Down
1 change: 1 addition & 0 deletions resource/network/filter.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Package network access
package network

import (
Expand Down
1 change: 1 addition & 0 deletions resource/network/reader/reader.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Package reader access
package reader

import (
Expand Down
14 changes: 14 additions & 0 deletions resource/projectReader.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,30 @@
// Package resource access
package resource

import (
"github.com/goat-project/goat-os/result"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack/identity/v3/projects"
"github.com/gophercloud/gophercloud/pagination"
log "github.com/sirupsen/logrus"
)

// ProjectReader structure for a Reader which reads an array of projects.
type ProjectReader struct {
ID string
}

// ReadResources reads an array of projects.
func (pr *ProjectReader) ReadResources(client *gophercloud.ServiceClient) pagination.Pager {
return projects.ListAvailable(client)
}

// ReadResource reads a project by ID.
func (pr *ProjectReader) ReadResource(client *gophercloud.ServiceClient) result.Result {

r, err := projects.Get(client, pr.ID).Extract()
if err != nil {
log.WithFields(log.Fields{"error": "GET request for project details failed"}).Fatal("error project info fetching")
}
return r
}
1 change: 1 addition & 0 deletions resource/server/filter.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Package server access
package server

import (
Expand Down
Loading
Loading