File: networks_peers.go

package info (click to toggle)
incus 6.0.5-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 24,392 kB
  • sloc: sh: 16,313; ansic: 3,121; python: 457; makefile: 337; ruby: 51; sql: 50; lisp: 6
file content (170 lines) | stat: -rw-r--r-- 6,256 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
//go:build linux && cgo && !agent

package cluster

import (
	"context"
	"database/sql"
	"errors"
	"fmt"

	"github.com/lxc/incus/v6/shared/api"
)

// Code generation directives.
//
//generate-database:mapper target networks_peers.mapper.go
//generate-database:mapper reset -i -b "//go:build linux && cgo && !agent"
//
//generate-database:mapper stmt -e network_peer objects
//generate-database:mapper stmt -e network_peer objects-by-Name
//generate-database:mapper stmt -e network_peer objects-by-ID
//generate-database:mapper stmt -e network_peer objects-by-NetworkID
//generate-database:mapper stmt -e network_peer objects-by-TargetNetworkID
//generate-database:mapper stmt -e network_peer objects-by-NetworkID-and-Name
//generate-database:mapper stmt -e network_peer objects-by-NetworkID-and-ID
//generate-database:mapper stmt -e network_peer objects-by-NetworkID-and-TargetNetworkProject-and-TargetNetworkName
//generate-database:mapper stmt -e network_peer objects-by-Type-and-TargetNetworkProject-and-TargetNetworkName
//generate-database:mapper stmt -e network_peer create struct=NetworkPeer
//generate-database:mapper stmt -e network_peer id
//generate-database:mapper stmt -e network_peer update struct=NetworkPeer
//generate-database:mapper stmt -e network_peer delete-by-NetworkID-and-ID
//
//generate-database:mapper method -i -e network_peer GetMany references=Config
//generate-database:mapper method -i -e network_peer GetOne struct=NetworkPeer
//generate-database:mapper method -i -e network_peer Exists struct=NetworkPeer
//generate-database:mapper method -i -e network_peer Create references=Config
//generate-database:mapper method -i -e network_peer ID struct=NetworkPeer
//generate-database:mapper method -i -e network_peer DeleteOne-by-NetworkID-and-ID
//generate-database:mapper method -i -e network_peer Update struct=NetworkPeer references=Config

const (
	// NetworkPeerTypeLocal represents a local peer connection.
	NetworkPeerTypeLocal = iota

	// NetworkPeerTypeRemote represents a remote peer connection.
	NetworkPeerTypeRemote
)

// NetworkPeerTypeNames maps peer types (integers) to their API representation (string).
var NetworkPeerTypeNames = map[int]string{
	NetworkPeerTypeLocal:  "local",
	NetworkPeerTypeRemote: "remote",
}

// NetworkPeerTypes maps peer strings to their internal representation (integers).
var NetworkPeerTypes = map[string]int{
	NetworkPeerTypeNames[NetworkPeerTypeLocal]:  NetworkPeerTypeLocal,
	NetworkPeerTypeNames[NetworkPeerTypeRemote]: NetworkPeerTypeRemote,
}

// NetworkPeer is a value object holding db-related details about a network peer.
// Fields correspond to the columns in the networks_peers table.
// generate-database will create CRUD methods and config helpers automatically.
type NetworkPeer struct {
	ID                         int64
	NetworkID                  int64  `db:"primary=yes&column=network_id"`
	Name                       string `db:"primary=yes"`
	Description                string
	Type                       int
	TargetNetworkProject       sql.NullString
	TargetNetworkName          sql.NullString
	TargetNetworkIntegrationID sql.NullInt64
	TargetNetworkID            sql.NullInt64
}

// NetworkPeerFilter specifies potential query parameter fields.
type NetworkPeerFilter struct {
	ID        *int64
	NetworkID *int64
	Name      *string
	Type      *int

	TargetNetworkProject       *string
	TargetNetworkName          *string
	TargetNetworkIntegrationID *int64
	TargetNetworkID            *int64
}

// NetworkPeerConnection represents a peer connection.
type NetworkPeerConnection struct {
	NetworkName string
	PeerName    string
}

// ToAPI converts the database NetworkPeer to API type.
func (n *NetworkPeer) ToAPI(ctx context.Context, tx *sql.Tx) (*api.NetworkPeer, error) {
	configMap, err := GetNetworkPeerConfig(ctx, tx, int(n.ID))
	if err != nil {
		return nil, err
	}

	resp := api.NetworkPeer{
		NetworkPeerPut: api.NetworkPeerPut{
			Description: n.Description,
			Config:      configMap,
		},
		Name:          n.Name,
		TargetProject: n.TargetNetworkProject.String,
		TargetNetwork: n.TargetNetworkName.String,
		Type:          NetworkPeerTypeNames[n.Type],
		UsedBy:        []string{},
	}

	if n.TargetNetworkID.Valid {
		// This is a workaround until networks themselves are ported over to the generator.
		dest := func(scan func(dest ...any) error) error {
			err := scan(&resp.TargetNetwork, &resp.TargetProject)
			if err != nil {
				return err
			}

			return nil
		}

		err := scan(ctx, tx, "SELECT networks.name, projects.name FROM networks JOIN projects ON networks.project_id=projects.id WHERE networks.id=?", dest, n.TargetNetworkID)
		if err != nil {
			return nil, fmt.Errorf("Failed to fetch from \"networks\" table: %w", err)
		}
	}

	// Get the target integration name if needed.
	if n.Type == NetworkPeerTypeRemote {
		idInt := int(n.TargetNetworkIntegrationID.Int64)
		integrations, err := GetNetworkIntegrations(ctx, tx, NetworkIntegrationFilter{ID: &idInt})
		if err != nil {
			return nil, err
		}

		if len(integrations) != 1 {
			return nil, errors.New("Couldn't find network integration")
		}

		resp.TargetIntegration = integrations[0].Name
		resp.Status = api.NetworkStatusCreated
	} else {
		// Peer has mutual peering from target network.
		if n.TargetNetworkName.String != "" && n.TargetNetworkProject.String != "" {
			if n.TargetNetworkID.Valid {
				// Peer is in a conflicting state with both the peer network ID and net/project names set.
				// Peer net/project names should only be populated before the peer is linked with a peer network ID.
				resp.Status = api.NetworkStatusErrored
			} else {
				// Peer isn't linked to a mutual peer on the target network yet but has joining details.
				resp.Status = api.NetworkStatusPending
			}
		} else {
			if n.TargetNetworkID.Valid {
				// Peer is linked to an mutual peer on the target network.
				resp.Status = api.NetworkStatusCreated
			} else {
				// Peer isn't linked to a mutual peer on the target network yet and has no joining details.
				// Perhaps it was formerly joined (and had its joining details cleared) and subsequently
				// the target peer removed its peering entry.
				resp.Status = api.NetworkStatusErrored
			}
		}
	}

	return &resp, nil
}