Remove orphan host_software and software before adding fk constriants (#1760)

This commit is contained in:
Tomas Touceda
2021-08-23 13:42:43 -03:00
committed by GitHub
parent 8b4c6a1dd7
commit b7a65e920a
2 changed files with 82 additions and 0 deletions
@@ -30,6 +30,16 @@ func Up_20210819131107(tx *sql.Tx) error {
}
}
// Clear any orphan software and host_software
_, err = tx.Exec(`DELETE FROM host_software WHERE NOT EXISTS (select 1 from hosts h where h.id=host_software.host_id)`)
if err != nil {
return errors.Wrap(err, "clearing orphan host_software")
}
_, err = tx.Exec(`DELETE FROM software WHERE NOT EXISTS (select 1 from host_software hs where hs.software_id=software.id)`)
if err != nil {
return errors.Wrap(err, "clearing orphan software")
}
if _, err := tx.Exec(`
ALTER TABLE host_software
ADD FOREIGN KEY host_software_hosts_fk(host_id) REFERENCES hosts (id) ON DELETE CASCADE,
+72
View File
@@ -9,13 +9,16 @@ import (
"path"
"runtime"
"testing"
"time"
"github.com/DATA-DOG/go-sqlmock"
"github.com/VividCortex/mysqlerr"
"github.com/WatchBeam/clock"
"github.com/fleetdm/fleet/v4/server/config"
"github.com/fleetdm/fleet/v4/server/datastore/mysql/migrations/tables"
"github.com/fleetdm/fleet/v4/server/fleet"
"github.com/fleetdm/fleet/v4/server/ptr"
"github.com/fleetdm/fleet/v4/server/test"
"github.com/go-kit/kit/log"
"github.com/go-sql-driver/mysql"
"github.com/jmoiron/sqlx"
@@ -510,3 +513,72 @@ func TestMigrations(t *testing.T) {
base := path.Dir(filename)
require.NoError(t, ioutil.WriteFile(path.Join(base, "schema.sql"), stdoutBuf.Bytes(), 0o655))
}
func Test20210819131107_AddCascadeToHostSoftware(t *testing.T) {
// Create the database (must use raw MySQL client to do this)
db, err := sql.Open(
"mysql",
fmt.Sprintf("%s:%s@tcp(%s)/?multiStatements=true", testUsername, testPassword, testAddress),
)
require.NoError(t, err)
defer db.Close()
_, err = db.Exec("DROP DATABASE IF EXISTS Test20210819131107_AddCascadeToHostSoftware; CREATE DATABASE Test20210819131107_AddCascadeToHostSoftware;")
require.NoError(t, err)
// Create a datastore client in order to run migrations as usual
config := config.MysqlConfig{
Username: testUsername,
Password: testPassword,
Address: testAddress,
Database: "Test20210819131107_AddCascadeToHostSoftware",
}
ds, err := New(config, clock.NewMockClock(), Logger(log.NewNopLogger()), LimitAttempts(1))
require.NoError(t, err)
defer ds.Close()
for {
version, err := tables.MigrationClient.GetDBVersion(ds.db.DB)
require.NoError(t, err)
// break right before the the constraint migration
if version == 20210818182258 {
break
}
require.NoError(t, tables.MigrationClient.UpByOne(ds.db.DB, ""))
}
host1 := test.NewHost(t, ds, "host1", "", "host1key", "host1uuid", time.Now())
host2 := test.NewHost(t, ds, "host2", "", "host2key", "host2uuid", time.Now())
soft1 := fleet.HostSoftware{
Modified: true,
Software: []fleet.Software{
{Name: "foo", Version: "0.0.1", Source: "chrome_extensions"},
{Name: "foo", Version: "0.0.3", Source: "chrome_extensions"},
},
}
host1.HostSoftware = soft1
soft2 := fleet.HostSoftware{
Modified: true,
Software: []fleet.Software{
{Name: "foo", Version: "0.0.2", Source: "chrome_extensions"},
{Name: "foo", Version: "0.0.3", Source: "chrome_extensions"},
{Name: "bar", Version: "0.0.3", Source: "deb_packages"},
},
}
host2.HostSoftware = soft2
host2.Modified = true
require.NoError(t, ds.SaveHostSoftware(host1))
require.NoError(t, ds.SaveHostSoftware(host2))
require.NoError(t, ds.DeleteHost(host1.ID))
require.NoError(t, tables.MigrationClient.UpByOne(ds.db.DB, ""))
// Make sure we don't delete more than we need
hostCheck, err := ds.Host(host2.ID)
require.NoError(t, err)
require.NoError(t, ds.LoadHostSoftware(hostCheck))
require.Len(t, hostCheck.Software, 3)
}