refactor(docker): strongly type snapshot [EE-3256]

fixes [EE-3256]
pull/6991/head
Chaim Lev-Ari 2022-05-26 15:34:34 +03:00
parent ca30efeca7
commit 0b2217a916
4 changed files with 125 additions and 42 deletions

View File

@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"log" "log"
"github.com/docker/docker/api/types/volume"
"github.com/portainer/portainer/api/dataservices/errors" "github.com/portainer/portainer/api/dataservices/errors"
portainer "github.com/portainer/portainer/api" portainer "github.com/portainer/portainer/api"
@ -206,18 +207,18 @@ func (m *Migrator) updateVolumeResourceControlToDB32() error {
endpointDockerID, err := snapshotutils.FetchDockerID(snapshot) endpointDockerID, err := snapshotutils.FetchDockerID(snapshot)
if err != nil { if err != nil {
log.Printf("[WARN] [database,migrator,v31] [message: failed fetching environment docker id] [err: %s]", err) log.Printf("[WARN] [bolt,migrator,v31] [message: failed fetching environment docker id] [err: %s]", err)
continue continue
} }
if volumesData, done := snapshot.SnapshotRaw.Volumes.(map[string]interface{}); done { volumesData := snapshot.SnapshotRaw.Volumes
if volumesData["Volumes"] == nil { if volumesData.Volumes == nil {
log.Println("[DEBUG] [volume migration] [message: no volume data found]") log.Println("[DEBUG] [volume migration] [message: no volume data found]")
continue continue
}
findResourcesToUpdateForDB32(endpointDockerID, volumesData, toUpdate, volumeResourceControls)
} }
findResourcesToUpdateToDB32(endpointDockerID, volumesData, toUpdate, volumeResourceControls)
} }
for _, resourceControl := range volumeResourceControls { for _, resourceControl := range volumeResourceControls {
@ -240,18 +241,11 @@ func (m *Migrator) updateVolumeResourceControlToDB32() error {
return nil return nil
} }
func findResourcesToUpdateForDB32(dockerID string, volumesData map[string]interface{}, toUpdate map[portainer.ResourceControlID]string, volumeResourceControls map[string]*portainer.ResourceControl) { func findResourcesToUpdateToDB32(dockerID string, volumesData volume.VolumeListOKBody, toUpdate map[portainer.ResourceControlID]string, volumeResourceControls map[string]*portainer.ResourceControl) {
volumes := volumesData["Volumes"].([]interface{}) volumes := volumesData.Volumes
for _, volumeMeta := range volumes { for _, volume := range volumes {
volume := volumeMeta.(map[string]interface{}) volumeName := volume.Name
volumeName, nameExist := volume["Name"].(string) createTime := volume.CreatedAt
if !nameExist {
continue
}
createTime, createTimeExist := volume["CreatedAt"].(string)
if !createTimeExist {
continue
}
oldResourceID := fmt.Sprintf("%s%s", volumeName, createTime) oldResourceID := fmt.Sprintf("%s%s", volumeName, createTime)
resourceControl, ok := volumeResourceControls[oldResourceID] resourceControl, ok := volumeResourceControls[oldResourceID]

View File

@ -70,10 +70,103 @@
"DockerSnapshotRaw": { "DockerSnapshotRaw": {
"Containers": null, "Containers": null,
"Images": null, "Images": null,
"Info": null, "Info": {
"Architecture": "",
"BridgeNfIp6tables": false,
"BridgeNfIptables": false,
"CPUSet": false,
"CPUShares": false,
"CgroupDriver": "",
"ContainerdCommit": {
"Expected": "",
"ID": ""
},
"Containers": 0,
"ContainersPaused": 0,
"ContainersRunning": 0,
"ContainersStopped": 0,
"CpuCfsPeriod": false,
"CpuCfsQuota": false,
"Debug": false,
"DefaultRuntime": "",
"DockerRootDir": "",
"Driver": "",
"DriverStatus": null,
"ExperimentalBuild": false,
"GenericResources": null,
"HttpProxy": "",
"HttpsProxy": "",
"ID": "",
"IPv4Forwarding": false,
"Images": 0,
"IndexServerAddress": "",
"InitBinary": "",
"InitCommit": {
"Expected": "",
"ID": ""
},
"Isolation": "",
"KernelMemory": false,
"KernelMemoryTCP": false,
"KernelVersion": "",
"Labels": null,
"LiveRestoreEnabled": false,
"LoggingDriver": "",
"MemTotal": 0,
"MemoryLimit": false,
"NCPU": 0,
"NEventsListener": 0,
"NFd": 0,
"NGoroutines": 0,
"Name": "",
"NoProxy": "",
"OSType": "",
"OSVersion": "",
"OomKillDisable": false,
"OperatingSystem": "",
"PidsLimit": false,
"Plugins": {
"Authorization": null,
"Log": null,
"Network": null,
"Volume": null
},
"RegistryConfig": null,
"RuncCommit": {
"Expected": "",
"ID": ""
},
"Runtimes": null,
"SecurityOptions": null,
"ServerVersion": "",
"SwapLimit": false,
"Swarm": {
"ControlAvailable": false,
"Error": "",
"LocalNodeState": "",
"NodeAddr": "",
"NodeID": "",
"RemoteManagers": null
},
"SystemTime": "",
"Warnings": null
},
"Networks": null, "Networks": null,
"Version": null, "Version": {
"Volumes": null "ApiVersion": "",
"Arch": "",
"GitCommit": "",
"GoVersion": "",
"Os": "",
"Platform": {
"Name": ""
},
"Version": ""
},
"Volumes": {
"Volumes": null,
"Warnings": null
}
}, },
"DockerVersion": "20.10.13", "DockerVersion": "20.10.13",
"HealthyContainerCount": 0, "HealthyContainerCount": 0,

View File

@ -188,24 +188,17 @@ func (service *Service) snapshotEndpoints() error {
// FetchDockerID fetches info.Swarm.Cluster.ID if environment(endpoint) is swarm and info.ID otherwise // FetchDockerID fetches info.Swarm.Cluster.ID if environment(endpoint) is swarm and info.ID otherwise
func FetchDockerID(snapshot portainer.DockerSnapshot) (string, error) { func FetchDockerID(snapshot portainer.DockerSnapshot) (string, error) {
info, done := snapshot.SnapshotRaw.Info.(map[string]interface{}) info := snapshot.SnapshotRaw.Info
if !done {
return "", errors.New("failed getting snapshot info")
}
if !snapshot.Swarm { if !snapshot.Swarm {
return info["ID"].(string), nil return info.ID, nil
} }
if info["Swarm"] == nil { swarmInfo := info.Swarm
return "", errors.New("swarm environment is missing swarm info snapshot") if swarmInfo.Cluster == nil {
}
swarmInfo := info["Swarm"].(map[string]interface{})
if swarmInfo["Cluster"] == nil {
return "", errors.New("swarm environment is missing cluster info snapshot") return "", errors.New("swarm environment is missing cluster info snapshot")
} }
clusterInfo := swarmInfo["Cluster"].(map[string]interface{}) clusterInfo := swarmInfo.Cluster
return clusterInfo["ID"].(string), nil return clusterInfo.ID, nil
} }

View File

@ -5,6 +5,8 @@ import (
"io" "io"
"time" "time"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/volume"
gittypes "github.com/portainer/portainer/api/git/types" gittypes "github.com/portainer/portainer/api/git/types"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
) )
@ -191,13 +193,14 @@ type (
} }
// DockerSnapshotRaw represents all the information related to a snapshot as returned by the Docker API // DockerSnapshotRaw represents all the information related to a snapshot as returned by the Docker API
DockerSnapshotRaw struct { DockerSnapshotRaw struct {
Containers interface{} `json:"Containers"` Containers []types.Container `json:"Containers"`
Volumes interface{} `json:"Volumes"` Volumes volume.VolumeListOKBody `json:"Volumes"`
Networks interface{} `json:"Networks"` Networks []types.NetworkResource `json:"Networks"`
Images interface{} `json:"Images"` Images []types.ImageSummary `json:"Images"`
Info interface{} `json:"Info"` Info types.Info `json:"Info"`
Version interface{} `json:"Version"` Version types.Version `json:"Version"`
} }
// EdgeGroup represents an Edge group // EdgeGroup represents an Edge group