@@ -13,10 +13,27 @@ package coordinator
1313import (
1414 "context"
1515 "errors"
16+ "fmt"
1617 "net"
18+ << << << < HEAD
1719 "testing"
1820 "time"
1921
22+ == == == =
23+ "net/http"
24+ "net/http/httptest"
25+ "os"
26+ "path/filepath"
27+ "strings"
28+ "sync"
29+ "testing"
30+ "time"
31+
32+ "github.com/elastic/elastic-agent-client/v7/pkg/proto"
33+ "github.com/elastic/elastic-agent/internal/pkg/fleetapi/acker"
34+ "github.com/elastic/elastic-agent/internal/pkg/testutils"
35+
36+ >> >> >> > a7a76f6e1 (Enhancement / 5235 use disk space error to set upgrade detail in coordinator (#9392 ))
2037 "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/status"
2138 "go.opentelemetry.io/collector/component/componentstatus"
2239 "go.opentelemetry.io/collector/confmap"
@@ -28,8 +45,15 @@ import (
2845 "github.com/elastic/elastic-agent-libs/logp"
2946 "github.com/elastic/elastic-agent/internal/pkg/agent/application/info"
3047 "github.com/elastic/elastic-agent/internal/pkg/agent/application/monitoring/reload"
48+ << << << < HEAD
49+ == == == =
50+ "github.com/elastic/elastic-agent/internal/pkg/agent/application/paths"
51+ "github.com/elastic/elastic-agent/internal/pkg/agent/application/reexec"
52+ "github.com/elastic/elastic-agent/internal/pkg/agent/application/secret"
53+ >> >> >> > a7a76f6e1 (Enhancement / 5235 use disk space error to set upgrade detail in coordinator (#9392 ))
3154 "github.com/elastic/elastic-agent/internal/pkg/agent/application/upgrade"
3255 "github.com/elastic/elastic-agent/internal/pkg/agent/application/upgrade/artifact"
56+ upgradeErrors "github.com/elastic/elastic-agent/internal/pkg/agent/application/upgrade/artifact/download/errors"
3357 "github.com/elastic/elastic-agent/internal/pkg/agent/application/upgrade/details"
3458 "github.com/elastic/elastic-agent/internal/pkg/agent/transpiler"
3559 "github.com/elastic/elastic-agent/internal/pkg/config"
@@ -1293,3 +1317,252 @@ func (fs *fakeMonitoringServer) Reset() {
12931317func (fs * fakeMonitoringServer ) Addr () net.Addr {
12941318 return nil
12951319}
1320+ << << << < HEAD
1321+ == == == =
1322+
1323+ func TestMergeFleetConfig (t * testing.T ) {
1324+ testutils .InitStorage (t )
1325+
1326+ cfg := map [string ]interface {}{
1327+ "fleet" : map [string ]interface {}{
1328+ "enabled" : true ,
1329+ "kibana" : map [string ]interface {}{"host" : "demo" },
1330+ "access_api_key" : "123" ,
1331+ },
1332+ "agent" : map [string ]interface {}{
1333+ "grpc" : map [string ]interface {}{
1334+ "port" : uint16 (6790 ),
1335+ },
1336+ },
1337+ }
1338+
1339+ path := paths .AgentConfigFile ()
1340+ store , err := storage .NewEncryptedDiskStore (t .Context (), path )
1341+ require .NoError (t , err )
1342+
1343+ rawConfig := config .MustNewConfigFrom (cfg )
1344+ conf , err := mergeFleetConfig (t .Context (), rawConfig , store )
1345+ require .NoError (t , err )
1346+ assert .NotNil (t , conf )
1347+ assert .Equal (t , conf .Fleet .Enabled , cfg ["fleet" ].(map [string ]interface {})["enabled" ])
1348+ assert .Equal (t , conf .Fleet .AccessAPIKey , cfg ["fleet" ].(map [string ]interface {})["access_api_key" ])
1349+ assert .Equal (t , conf .Settings .GRPC .Port , cfg ["agent" ].(map [string ]interface {})["grpc" ].(map [string ]interface {})["port" ].(uint16 ))
1350+ }
1351+
1352+ func TestComputeEnrollOptions (t * testing.T ) {
1353+ testutils .InitStorage (t )
1354+ tmp := t .TempDir ()
1355+
1356+ storePath := filepath .Join (tmp , "fleet.enc" )
1357+ cfgPath := filepath .Join (tmp , "elastic-agent.yml" )
1358+
1359+ cfg := map [string ]interface {}{
1360+ "fleet" : map [string ]interface {}{
1361+ "enabled" : true ,
1362+ "access_api_key" : "123" ,
1363+ },
1364+ "agent" : map [string ]interface {}{
1365+ "grpc" : map [string ]interface {}{
1366+ "port" : uint16 (6790 ),
1367+ },
1368+ },
1369+ }
1370+
1371+ rawAgentConfigData , err := yaml .Marshal (cfg )
1372+ require .NoError (t , err )
1373+
1374+ require .NoError (t , os .WriteFile (cfgPath , rawAgentConfigData , 0644 ))
1375+
1376+ store , err := storage .NewEncryptedDiskStore (t .Context (), storePath )
1377+ require .NoError (t , err )
1378+
1379+ fleetConfig := `fleet:
1380+ hosts: [localhost:1234]
1381+ ssl:
1382+ ca_sha256: ["sha1", "sha2"]
1383+ verification_mode: none
1384+ proxy_url: http://proxy.example.com:8080
1385+ proxy_disable: false
1386+ proxy_headers:
1387+ Proxy-Authorization: "Bearer token"
1388+ Custom-Header: "custom-value"
1389+ enrollment_token: enrollment-token-123
1390+ force: true
1391+ insecure: true
1392+ agent:
1393+ id: test-agent-id
1394+ `
1395+ require .NoError (t , store .Save (bytes .NewReader ([]byte (fleetConfig ))))
1396+
1397+ options , err := computeEnrollOptions (t .Context (), cfgPath , storePath )
1398+ require .NoError (t , err )
1399+
1400+ require .NoError (t , err )
1401+ assert .NotNil (t , options )
1402+
1403+ assert .Equal (t , "123" , options .EnrollAPIKey , "EnrollAPIKey mismatch" )
1404+ assert .Equal (t , "http://localhost:1234" , options .URL , "URL mismatch" )
1405+
1406+ assert .Equal (t , []string {"sha1" , "sha2" }, options .CASha256 , "CASha256 mismatch" )
1407+ assert .Equal (t , true , options .Insecure , "Insecure mismatch" )
1408+ assert .Equal (t , "test-agent-id" , options .ID , "ID mismatch" )
1409+ assert .Equal (t , "http://proxy.example.com:8080" , options .ProxyURL , "ProxyURL mismatch" )
1410+ assert .Equal (t , false , options .ProxyDisabled , "ProxyDisabled mismatch" )
1411+ expectedProxyHeaders := map [string ]string {
1412+ "Proxy-Authorization" : "Bearer token" ,
1413+ "Custom-Header" : "custom-value" ,
1414+ }
1415+ assert .Equal (t , expectedProxyHeaders , options .ProxyHeaders , "ProxyHeaders mismatch" )
1416+ }
1417+
1418+ func TestHasEndpoint (t * testing.T ) {
1419+ testCases := []struct {
1420+ name string
1421+ state State
1422+ expected bool
1423+ }{
1424+ {
1425+ "endpoint" ,
1426+ State {
1427+ Components : []runtime.ComponentComponentState {
1428+ {
1429+ Component : component.Component {
1430+ InputType : endpoint ,
1431+ },
1432+ },
1433+ },
1434+ },
1435+ true ,
1436+ },
1437+ {
1438+ "no endpoint" ,
1439+ State {
1440+ Components : []runtime.ComponentComponentState {
1441+ {
1442+ Component : component.Component {
1443+ InputType : "not endpoint" ,
1444+ },
1445+ },
1446+ },
1447+ },
1448+ false ,
1449+ },
1450+
1451+ {
1452+ "no component" ,
1453+ State {
1454+ Components : []runtime.ComponentComponentState {},
1455+ },
1456+ false ,
1457+ },
1458+ }
1459+
1460+ for _ , tc := range testCases {
1461+ t .Run (tc .name , func (t * testing.T ) {
1462+ c := & Coordinator {
1463+ state : tc .state ,
1464+ }
1465+
1466+ result := c .HasEndpoint ()
1467+ assert .Equal (t , tc .expected , result , "HasEndpoint result mismatch" )
1468+ })
1469+ }
1470+ }
1471+
1472+ type mockUpgradeManager struct {
1473+ upgradeErr error
1474+ }
1475+
1476+ func (m * mockUpgradeManager ) Upgradeable () bool {
1477+ return true
1478+ }
1479+
1480+ func (m * mockUpgradeManager ) Reload (cfg * config.Config ) error {
1481+ return nil
1482+ }
1483+
1484+ func (m * mockUpgradeManager ) Upgrade (ctx context.Context , version string , rollback bool , sourceURI string , action * fleetapi.ActionUpgrade , details * details.Details , skipVerifyOverride bool , skipDefaultPgp bool , pgpBytes ... string ) (_ reexec.ShutdownCallbackFn , err error ) {
1485+ return nil , m .upgradeErr
1486+ }
1487+
1488+ func (m * mockUpgradeManager ) Ack (ctx context.Context , acker acker.Acker ) error {
1489+ return nil
1490+ }
1491+
1492+ func (m * mockUpgradeManager ) AckAction (ctx context.Context , acker acker.Acker , action fleetapi.Action ) error {
1493+ return nil
1494+ }
1495+
1496+ func (m * mockUpgradeManager ) MarkerWatcher () upgrade.MarkerWatcher {
1497+ return nil
1498+ }
1499+
1500+ func TestCoordinator_Upgrade_InsufficientDiskSpaceError (t * testing.T ) {
1501+ log , _ := loggertest .New ("coordinator-insufficient-disk-space-test" )
1502+
1503+ mockUpgradeManager := & mockUpgradeManager {
1504+ upgradeErr : fmt .Errorf ("wrapped: %w" , upgradeErrors .ErrInsufficientDiskSpace ),
1505+ }
1506+
1507+ initialState := State {
1508+ CoordinatorState : agentclient .Healthy ,
1509+ CoordinatorMessage : "Running" ,
1510+ }
1511+
1512+ coord := & Coordinator {
1513+ state : initialState ,
1514+ logger : log ,
1515+ upgradeMgr : mockUpgradeManager ,
1516+ stateBroadcaster : broadcaster .New (initialState , 64 , 32 ),
1517+ overrideStateChan : make (chan * coordinatorOverrideState ),
1518+ upgradeDetailsChan : make (chan * details.Details ),
1519+ }
1520+
1521+ wg := sync.WaitGroup {}
1522+ wg .Add (2 )
1523+
1524+ overrideStates := []agentclient.State {}
1525+ go func () {
1526+ state1 := <- coord .overrideStateChan
1527+ overrideStates = append (overrideStates , state1 .state )
1528+
1529+ state2 := <- coord .overrideStateChan
1530+ if state2 != nil {
1531+ overrideStates = append (overrideStates , state2 .state )
1532+ }
1533+
1534+ wg .Done ()
1535+ }()
1536+
1537+ upgradeDetails := []* details.Details {}
1538+ go func () {
1539+ upgradeDetails = append (upgradeDetails , <- coord .upgradeDetailsChan )
1540+ upgradeDetails = append (upgradeDetails , <- coord .upgradeDetailsChan )
1541+ wg .Done ()
1542+ }()
1543+
1544+ err := coord .Upgrade (t .Context (), "" , "" , nil )
1545+ require .Error (t , err )
1546+ require .Equal (t , err , upgradeErrors .ErrInsufficientDiskSpace )
1547+
1548+ wg .Wait ()
1549+
1550+ require .Equal (t , []agentclient.State {agentclient .Upgrading }, overrideStates )
1551+
1552+ require .Equal (t , []* details.Details {
1553+ {
1554+ TargetVersion : "" ,
1555+ State : details .StateRequested ,
1556+ ActionID : "" ,
1557+ },
1558+ {
1559+ TargetVersion : "" ,
1560+ State : details .StateFailed ,
1561+ Metadata : details.Metadata {
1562+ FailedState : details .StateRequested ,
1563+ ErrorMsg : upgradeErrors .ErrInsufficientDiskSpace .Error (),
1564+ },
1565+ },
1566+ }, upgradeDetails )
1567+ }
1568+ >> >> >> > a7a76f6e1 (Enhancement / 5235 use disk space error to set upgrade detail in coordinator (#9392 ))
0 commit comments