Skip to content
Merged
Show file tree
Hide file tree
Changes from 36 commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
b1e1624
update project structure and apply some fixes
Jan 23, 2024
287c9fd
update golangci-lint version in test workflow
Jan 23, 2024
73ecab3
bump google.golang.org/grpc and golang.org/x/net
Jan 24, 2024
1399eab
add baremetal/drivers and blockstorage/snapshots
Jan 25, 2024
ecdd35d
update baremetal drivers
Jan 30, 2024
41460ea
add baremetal tables
Feb 1, 2024
4b0f3da
add blockstorage/qos
Feb 2, 2024
d7b2de7
add availabiilty zones, backups, limits and qos for blockstorage
Feb 2, 2024
26238b3
fix spec and baremetal microversion
Feb 5, 2024
1ecfa74
add blockstorage/limits
Feb 5, 2024
1881c27
add compute/images
Feb 6, 2024
fbaa606
add service info in table names
Feb 6, 2024
431c8c8
add compute/limits
Feb 6, 2024
01795ce
add compute/network
Feb 6, 2024
9d6ae8f
apply formatting
Feb 6, 2024
99a028f
add compute/secgroups and small fix on compute/limits
Feb 7, 2024
83cf966
implement spec validation and comment tables without resource
Feb 7, 2024
4af157e
fix blockstorage/limits columns types
Feb 7, 2024
ba7a3f4
use gophercloud blockstorage/limits struct
Feb 7, 2024
17c1416
add compute/tenantnetworks and compute/serverusage
Feb 8, 2024
3f3659a
add blockstorage/quotasets and blockstorage/services
Feb 9, 2024
378b61b
add blockstorage/quotasets_usage
Feb 9, 2024
3cda75e
fix blockstorage/volumes_backups and compute/limits
Feb 9, 2024
6a93f4d
update error handling
Feb 9, 2024
765f6a8
apply formatting
Feb 9, 2024
f46f3fd
add identity/domains, tenants and imageservice members
Feb 9, 2024
f832cfc
add identity/services
Feb 12, 2024
b30a03b
fix small bugs
Feb 12, 2024
19fa3ed
change endpoint names
Feb 12, 2024
ae888ed
update dependecies and apply formatting
Feb 13, 2024
89ba6cd
use tagtype from utils
Feb 13, 2024
d97acdb
add include/exclude tables in spec. With @gambu94
Feb 13, 2024
7b69d22
fix match func, add some additional tests. With @gambu94
Feb 14, 2024
7dbac8f
apply formatting
Feb 14, 2024
e411e67
chore: remove unused func, add all available tables changing the spec…
Feb 14, 2024
f87a210
new destination DB URI and minor fixes on limits to solve incremental…
Feb 22, 2024
e52ad38
chore: update deps
Feb 29, 2024
479f824
chore: revert api naming
Feb 29, 2024
357ddad
fix: image service renaming
Feb 29, 2024
3bb09fe
fix: remove x := x in for loops, reduntant with Go1.22
Feb 29, 2024
f085d76
fix: client getTables method
Feb 29, 2024
e39f4a2
update goreleaser ldflags
Feb 29, 2024
8cceeec
fix: add kind to plugin init and change to var for ldflags to work
Mar 1, 2024
90e2302
fix: remove deprecated API
Mar 1, 2024
97b1c35
fix: remove commented code and apply formatting
Mar 1, 2024
d724a46
fix: image members and instance security groups
Mar 1, 2024
292da01
add: identity groups, regions, registeredlimits and roles
Mar 1, 2024
978a353
replace internals with cq-plugin-utils lib
Mar 5, 2024
2a58b04
add identity catalog
Mar 5, 2024
640f5db
fix: identity/services and remove catalog
Mar 7, 2024
1798a29
bump to plugin-sdk v4.32.1 and gophercloud v1.11.0
Mar 7, 2024
b573d6f
add checks on input spec
Mar 7, 2024
0853ff7
add check on spec at plugin loading time
Mar 11, 2024
7ac5c76
fix: check spec endpoint is not nil
Mar 11, 2024
42122b0
chore: update cq-plugin-utils
Mar 11, 2024
6ca84bb
fix: update .gjthub ci
Mar 11, 2024
c803aa2
update .gitignore
Mar 11, 2024
c422a96
fix: prevent go doc fail when spec is empty
Mar 11, 2024
e225263
fix: change from goreleaser to makefile.
Mar 11, 2024
c5ceee3
fix: golangci-lint workflow
Mar 11, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
- name: golangci-lint
uses: golangci/golangci-lint-action@v3
with:
version: v1.51.2
version: v1.55.2
- name: Get dependencies
run: go get -t -d ./...
- name: Build
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# CloudQuery OpenStack Source Plugin

[![test](https://github.com/github.com/dihedron/cq-source-openstack/actions/workflows/test.yaml/badge.svg)](https://github.com/github.com/dihedron/cq-source-openstack/actions/workflows/test.yaml)
[![Go Report Card](https://goreportcard.com/badge/github.com/github.com/dihedron/cq-source-openstack)](https://goreportcard.com/report/github.com/github.com/dihedron/cq-source-openstack)
[![test](https://github.com/dihedron/cq-source-openstack/actions/workflows/test.yaml/badge.svg)](https://github.com/dihedron/cq-source-openstack/actions/workflows/test.yaml)
[![Go Report Card](https://goreportcard.com/badge/github.com/dihedron/cq-source-openstack)](https://goreportcard.com/report/github.com/dihedron/cq-source-openstack)

A source plugin for CloudQuery that loads data from OpenStack to any database, data warehouse or data lake supported by [CloudQuery](https://www.cloudquery.io/), such as PostgreSQL, BigQuery, Athena, and many more.

OpenStack is the most widely used open source cloud platform; it powers hundreds of private clouds and some public clouds too;.
OpenStack is the most widely used open source cloud platform; it powers hundreds of private clouds and some public clouds too.

## Links

Expand Down
28 changes: 14 additions & 14 deletions _test/docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
version: '3.7'
services:
cloudquery:
image: postgres:14
restart: unless-stopped
environment:
- POSTGRES_USER=cloudquery
- POSTGRES_PASSWORD=cloudquery
logging:
options:
max-size: 10m
max-file: "3"
ports:
- '5433:5432'
volumes:
- cloudquery_data:/var/lib/postgresql/data
cloudquery:
image: postgres:14
restart: unless-stopped
environment:
- POSTGRES_USER=cloudquery
- POSTGRES_PASSWORD=cloudquery
logging:
options:
max-size: 10m
max-file: "3"
ports:
- '5433:5432'
volumes:
- cloudquery_data:/var/lib/postgresql/data
volumes:
cloudquery_data:
external: false
27 changes: 18 additions & 9 deletions _test/openstack.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@ kind: source
spec:
name: openstack_lab
registry: local
path: "/data/workspaces/gomods/cq-source-openstack/dist/cq-source-openstack_linux_amd64_v1/cq-source-openstack"
path: "../dist/cq-source-openstack_linux_amd64_v1/cq-source-openstack"
version: v1.0.0
tables:
["openstack*"]
tables: ["openstack*"]
destinations:
- sqlite
# - postgresql
# - sqlite
- postgresql
spec:
endpoint_url: ${OPENSTACK_ENDPOINT_URL}
username: ${OPENSTACK_USERNAME}
Expand All @@ -18,14 +17,24 @@ spec:
domain_name: ${OPENSTACK_DOMAIN_NAME}
app_credential_id: ${OPENSTACK_APP_CREDENTIAL_ID}
app_credential_secret: ${OPENSTACK_APP_CREDENTIAL_SECRET}
included_tables: ["openstack*"]
excluded_tables:
[
"openstack_ironic*",
"openstack_nova_images",
"openstack_nova_networks",
"openstack_nova_secgroups",
"openstack_nova_tenant*",
"openstack_keystone_tenants",
]
# ---
# kind: source
# spec:
# name: gitlab_cloud
# path: cloudquery/gitlab
# version: v3.0.0
# tables: ["*"]
# destinations:
# destinations:
# - sqlite
# - postgresql
# spec:
Expand All @@ -45,8 +54,8 @@ spec:
name: postgresql
registry: github
path: cloudquery/postgresql
version: v7.1.6
version: v7.3.4
spec:
connection_string: postgresql://cloudquery:cloudquery@localhost:15433/cloudquery?sslmode=disable
# connection_string: postgresql://cloudquery:cloudquery@localhost:5432/cloudquery?sslmode=disable
connection_string: postgresql://cloudquery:cloudquery@${DB_POSTGRES_URL}:5433/cloudquery?sslmode=disable
# connection_string: postgresql://cloudquery:cloudquery@localhost:5432/cloudquery?sslmode=disable
# connection_string: postgresql://superset:superset@localhost:15432/superset?sslmode=disable
79 changes: 49 additions & 30 deletions client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ func New(ctx context.Context, logger zerolog.Logger, spec *Spec) (*Client, error

logger.Debug().Str("spec", format.ToJSON(spec)).Msg("plugin configuration")

err := spec.Validate()
if err != nil {
logger.Error().Err(err).Msg("invalid spec configuration")
return nil, fmt.Errorf("error spec not valid: %w", err)
}

auth := gophercloud.AuthOptions{
AllowReauth: true,
}
Expand Down Expand Up @@ -142,25 +148,28 @@ func (c *Client) initServiceClient(key ServiceType) (*gophercloud.ServiceClient,

const (
// defaults currently referring to Train
DefaultComputeV2Microversion = "2.79"
DefaultIdentityV3Microversion = "3.13"
DefaultBlockStorageV3Microversion = "3.59"
DefaultImageServiceV2Microversion = "2.9"
DefaultIronicV1Microversion = "1.58"
DefaultNovaV2Microversion = "2.79"
DefaultKeystoneV3Microversion = "3.13"
DefaultCinderV3Microversion = "3.59"
DefaultGlanceV2Microversion = "2.9"
)

type ServiceType string

const (
// IdentityV3 identifies the OpenStack Identity V3 service (Keystone).
IdentityV3 ServiceType = "openstack_identity_v3"
// IronicV1 identifies the OpenStack Baremetal V1 service (Ironic).
IronicV1 = "openstack_ironic_v1"
// KeystoneV3 identifies the OpenStack Identity V3 service (Keystone).
KeystoneV3 ServiceType = "openstack_keystone_v3"
// Compute identifies the penStack Compute V2 service (Nova).
ComputeV2 = "openstack_compute_v2"
// NetworkV2 identifies the OpenStack Network V2 service (Neutron).
NetworkV2 = "openstack_network_v2"
// BlockStorageV3 identifies the OpenStack Block Storage V3 service (Cinder).
BlockStorageV3 = "openstack_blockstorage_v3"
// ImageServiceV2 identifies the OpenStack Image Service V2 service (Glance).
ImageServiceV2 = "openstack_imageservice_v2"
NovaV2 = "openstack_nova_v2"
// NeutronV2 identifies the OpenStack Network V2 service (Neutron).
NeutronV2 = "openstack_neutron_v2"
// CinderV3 identifies the OpenStack Block Storage V3 service (Cinder).
CinderV3 = "openstack_cinder_v3"
// GlanceV2 identifies the OpenStack Image Service V2 service (Glance).
GlanceV2 = "openstack_glance_v2"
)

type serviceConfig struct {
Expand All @@ -169,49 +178,59 @@ type serviceConfig struct {
}

var serviceConfigMap = map[ServiceType]serviceConfig{
IdentityV3: {
IronicV1: {
newClient: openstack.NewBareMetalV1,
getMicroversion: func(spec *Spec) string {
microversion := DefaultIronicV1Microversion
if spec.IronicV1Microversion != nil {
microversion = *spec.IronicV1Microversion
}
return microversion
},
},
KeystoneV3: {
newClient: openstack.NewIdentityV3,
getMicroversion: func(spec *Spec) string {
microversion := DefaultIdentityV3Microversion
if spec.IdentityV3Microversion != nil {
microversion = *spec.IdentityV3Microversion
microversion := DefaultKeystoneV3Microversion
if spec.KeystoneV3Microversion != nil {
microversion = *spec.KeystoneV3Microversion
}
return microversion
},
},
ComputeV2: {
NovaV2: {
newClient: openstack.NewComputeV2,
getMicroversion: func(spec *Spec) string {
microversion := DefaultComputeV2Microversion
if spec.ComputeV2Microversion != nil {
microversion = *spec.ComputeV2Microversion
microversion := DefaultNovaV2Microversion
if spec.NovaV2Microversion != nil {
microversion = *spec.NovaV2Microversion
}
return microversion
},
},
NetworkV2: {
NeutronV2: {
newClient: openstack.NewNetworkV2,
getMicroversion: func(spec *Spec) string {
// TODO: check if we need to leverage/support micro-versions
return ""
},
},
BlockStorageV3: {
CinderV3: {
newClient: openstack.NewBlockStorageV3,
getMicroversion: func(spec *Spec) string {
microversion := DefaultBlockStorageV3Microversion
if spec.BlockStorageV3Microversion != nil {
microversion = *spec.BlockStorageV3Microversion
microversion := DefaultCinderV3Microversion
if spec.CinderV3Microversion != nil {
microversion = *spec.CinderV3Microversion
}
return microversion
},
},
ImageServiceV2: {
GlanceV2: {
newClient: openstack.NewImageServiceV2,
getMicroversion: func(spec *Spec) string {
microversion := DefaultImageServiceV2Microversion
if spec.ImageServiceV2Microversion != nil {
microversion = *spec.ImageServiceV2Microversion
microversion := DefaultGlanceV2Microversion
if spec.GlanceV2Microversion != nil {
microversion = *spec.GlanceV2Microversion
}
return microversion
},
Expand Down
59 changes: 40 additions & 19 deletions client/spec.go
Original file line number Diff line number Diff line change
@@ -1,28 +1,49 @@
package client

import (
"net/http"
"net/url"

"github.com/rs/zerolog/log"
)

type Spec struct {
EndpointUrl *string `json:"endpoint_url,omitempty" yaml:"endpoint_url,omitempty"`
UserID *string `json:"userid,omitempty" yaml:"userid,omitempty"`
Username *string `json:"username,omitempty" yaml:"username,omitempty"`
Password *string `json:"password,omitempty" yaml:"password,omitempty"`
Region *string `json:"region,omitempty" yaml:"region,omitempty"`
ProjectID *string `json:"project_id,omitempty" yaml:"project_id,omitempty"`
ProjectName *string `json:"project_name,omitempty" yaml:"project_name,omitempty"`
DomainID *string `json:"domain_id,omitempty" yaml:"domain_id,omitempty"`
DomainName *string `json:"domain_name,omitempty" yaml:"domain_name,omitempty"`
AccessToken *string `json:"access_token,omitempty" yaml:"access_token,omitempty"`
AppCredentialID *string `json:"app_credential_id,omitempty" yaml:"app_credential_id,omitempty"`
AppCredentialSecret *string `json:"app_credential_secret,omitempty" yaml:"app_credential_secret,omitempty"`
AllowReauth *bool `json:"allow_reauth,omitempty" yaml:"allow_reauth,omitempty"`
IdentityV3Microversion *string `json:"identity_v3_microversion,omitempty" yaml:"identity_v3_microversion,omitempty"`
ComputeV2Microversion *string `json:"compute_v2_microversion,omitempty" yaml:"compute_v2_microversion,omitempty"`
NetworkV2Microversion *string `json:"network_v2_microversion,omitempty" yaml:"network_v2_microversion,omitempty"`
BlockStorageV3Microversion *string `json:"blockstorage_v3_microversion,omitempty" yaml:"blockstorage_v3_microversion,omitempty"`
ImageServiceV2Microversion *string `json:"imageservice_v2_microversion,omitempty" yaml:"imageservice_v2_microversion,omitempty"`
EndpointUrl *string `json:"endpoint_url,omitempty" yaml:"endpoint_url,omitempty"`
UserID *string `json:"userid,omitempty" yaml:"userid,omitempty"`
Username *string `json:"username,omitempty" yaml:"username,omitempty"`
Password *string `json:"password,omitempty" yaml:"password,omitempty"`
Region *string `json:"region,omitempty" yaml:"region,omitempty"`
ProjectID *string `json:"project_id,omitempty" yaml:"project_id,omitempty"`
ProjectName *string `json:"project_name,omitempty" yaml:"project_name,omitempty"`
DomainID *string `json:"domain_id,omitempty" yaml:"domain_id,omitempty"`
DomainName *string `json:"domain_name,omitempty" yaml:"domain_name,omitempty"`
AccessToken *string `json:"access_token,omitempty" yaml:"access_token,omitempty"`
AppCredentialID *string `json:"app_credential_id,omitempty" yaml:"app_credential_id,omitempty"`
AppCredentialSecret *string `json:"app_credential_secret,omitempty" yaml:"app_credential_secret,omitempty"`
AllowReauth *bool `json:"allow_reauth,omitempty" yaml:"allow_reauth,omitempty"`
IronicV1Microversion *string `json:"ironic_v1_microversion,omitempty" yaml:"ironic_v1_microversion,omitempty"`
KeystoneV3Microversion *string `json:"keyston_v3_microversion,omitempty" yaml:"keyston_v3_microversion,omitempty"`
NovaV2Microversion *string `json:"nova_v2_microversion,omitempty" yaml:"nova_v2_microversion,omitempty"`
NeutronV2Microversion *string `json:"neutron_v2_microversion,omitempty" yaml:"neutron_v2_microversion,omitempty"`
CinderV3Microversion *string `json:"cinder_v3_microversion,omitempty" yaml:"cinder_v3_microversion,omitempty"`
GlanceV2Microversion *string `json:"glance_v2_microversion,omitempty" yaml:"glance_v2_microversion,omitempty"`
IncludedTables []string `json:"included_tables,omitempty" yaml:"included_tables,omitempty"`
ExcludedTables []string `json:"excluded_tables,omitempty" yaml:"excluded_tables,omitempty"`
}

func (s *Spec) Validate() error {
// TODO: implement
// Check that the endpoint URL is a valid URL
_, err := url.ParseRequestURI(*s.EndpointUrl)
if err != nil {
log.Error().Err(err).Msg("invalid endpoint URL")
return err
}
// Check that the endpoint URL is reachable
_, err = http.Get(*s.EndpointUrl)
if err != nil {
log.Error().Err(err).Msg("endpoint URL is unreachable")
return err
}
return nil
}

Expand Down
Loading