@@ -15,11 +15,25 @@ import (
1515 "errors"
1616 "fmt"
1717 "net"
18+ << << << < HEAD
19+ == == == =
20+ "net/http"
21+ "net/http/httptest"
22+ "os"
23+ "path/filepath"
24+ "strings"
25+ "sync"
26+ >> >> >> > a7a76f6e1 (Enhancement / 5235 use disk space error to set upgrade detail in coordinator (#9392 ))
1827 "testing"
1928 "time"
2029
2130 "github.com/elastic/elastic-agent-client/v7/pkg/proto"
31+ << << << < HEAD
2232 "github.com/elastic/elastic-agent/internal/pkg/otel/translate"
33+ == == == =
34+ "github.com/elastic/elastic-agent/internal/pkg/fleetapi/acker"
35+ "github.com/elastic/elastic-agent/internal/pkg/testutils"
36+ >> >> >> > a7a76f6e1 (Enhancement / 5235 use disk space error to set upgrade detail in coordinator (#9392 ))
2337
2438 "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/status"
2539 "go.opentelemetry.io/collector/component/componentstatus"
@@ -32,8 +46,15 @@ import (
3246 "github.com/elastic/elastic-agent-libs/logp"
3347 "github.com/elastic/elastic-agent/internal/pkg/agent/application/info"
3448 "github.com/elastic/elastic-agent/internal/pkg/agent/application/monitoring/reload"
49+ << << << < HEAD
50+ == == == =
51+ "github.com/elastic/elastic-agent/internal/pkg/agent/application/paths"
52+ "github.com/elastic/elastic-agent/internal/pkg/agent/application/reexec"
53+ "github.com/elastic/elastic-agent/internal/pkg/agent/application/secret"
54+ >> >> >> > a7a76f6e1 (Enhancement / 5235 use disk space error to set upgrade detail in coordinator (#9392 ))
3555 "github.com/elastic/elastic-agent/internal/pkg/agent/application/upgrade"
3656 "github.com/elastic/elastic-agent/internal/pkg/agent/application/upgrade/artifact"
57+ upgradeErrors "github.com/elastic/elastic-agent/internal/pkg/agent/application/upgrade/artifact/download/errors"
3758 "github.com/elastic/elastic-agent/internal/pkg/agent/application/upgrade/details"
3859 "github.com/elastic/elastic-agent/internal/pkg/agent/transpiler"
3960 "github.com/elastic/elastic-agent/internal/pkg/config"
@@ -1650,3 +1671,252 @@ func (fs *fakeMonitoringServer) Reset() {
16501671func (fs * fakeMonitoringServer ) Addr () net.Addr {
16511672 return nil
16521673}
1674+ << << << < HEAD
1675+ == == == =
1676+
1677+ func TestMergeFleetConfig (t * testing.T ) {
1678+ testutils .InitStorage (t )
1679+
1680+ cfg := map [string ]interface {}{
1681+ "fleet" : map [string ]interface {}{
1682+ "enabled" : true ,
1683+ "kibana" : map [string ]interface {}{"host" : "demo" },
1684+ "access_api_key" : "123" ,
1685+ },
1686+ "agent" : map [string ]interface {}{
1687+ "grpc" : map [string ]interface {}{
1688+ "port" : uint16 (6790 ),
1689+ },
1690+ },
1691+ }
1692+
1693+ path := paths .AgentConfigFile ()
1694+ store , err := storage .NewEncryptedDiskStore (t .Context (), path )
1695+ require .NoError (t , err )
1696+
1697+ rawConfig := config .MustNewConfigFrom (cfg )
1698+ conf , err := mergeFleetConfig (t .Context (), rawConfig , store )
1699+ require .NoError (t , err )
1700+ assert .NotNil (t , conf )
1701+ assert .Equal (t , conf .Fleet .Enabled , cfg ["fleet" ].(map [string ]interface {})["enabled" ])
1702+ assert .Equal (t , conf .Fleet .AccessAPIKey , cfg ["fleet" ].(map [string ]interface {})["access_api_key" ])
1703+ assert .Equal (t , conf .Settings .GRPC .Port , cfg ["agent" ].(map [string ]interface {})["grpc" ].(map [string ]interface {})["port" ].(uint16 ))
1704+ }
1705+
1706+ func TestComputeEnrollOptions (t * testing.T ) {
1707+ testutils .InitStorage (t )
1708+ tmp := t .TempDir ()
1709+
1710+ storePath := filepath .Join (tmp , "fleet.enc" )
1711+ cfgPath := filepath .Join (tmp , "elastic-agent.yml" )
1712+
1713+ cfg := map [string ]interface {}{
1714+ "fleet" : map [string ]interface {}{
1715+ "enabled" : true ,
1716+ "access_api_key" : "123" ,
1717+ },
1718+ "agent" : map [string ]interface {}{
1719+ "grpc" : map [string ]interface {}{
1720+ "port" : uint16 (6790 ),
1721+ },
1722+ },
1723+ }
1724+
1725+ rawAgentConfigData , err := yaml .Marshal (cfg )
1726+ require .NoError (t , err )
1727+
1728+ require .NoError (t , os .WriteFile (cfgPath , rawAgentConfigData , 0644 ))
1729+
1730+ store , err := storage .NewEncryptedDiskStore (t .Context (), storePath )
1731+ require .NoError (t , err )
1732+
1733+ fleetConfig := `fleet:
1734+ hosts: [localhost:1234]
1735+ ssl:
1736+ ca_sha256: ["sha1", "sha2"]
1737+ verification_mode: none
1738+ proxy_url: http://proxy.example.com:8080
1739+ proxy_disable: false
1740+ proxy_headers:
1741+ Proxy-Authorization: "Bearer token"
1742+ Custom-Header: "custom-value"
1743+ enrollment_token: enrollment-token-123
1744+ force: true
1745+ insecure: true
1746+ agent:
1747+ id: test-agent-id
1748+ `
1749+ require .NoError (t , store .Save (bytes .NewReader ([]byte (fleetConfig ))))
1750+
1751+ options , err := computeEnrollOptions (t .Context (), cfgPath , storePath )
1752+ require .NoError (t , err )
1753+
1754+ require .NoError (t , err )
1755+ assert .NotNil (t , options )
1756+
1757+ assert .Equal (t , "123" , options .EnrollAPIKey , "EnrollAPIKey mismatch" )
1758+ assert .Equal (t , "http://localhost:1234" , options .URL , "URL mismatch" )
1759+
1760+ assert .Equal (t , []string {"sha1" , "sha2" }, options .CASha256 , "CASha256 mismatch" )
1761+ assert .Equal (t , true , options .Insecure , "Insecure mismatch" )
1762+ assert .Equal (t , "test-agent-id" , options .ID , "ID mismatch" )
1763+ assert .Equal (t , "http://proxy.example.com:8080" , options .ProxyURL , "ProxyURL mismatch" )
1764+ assert .Equal (t , false , options .ProxyDisabled , "ProxyDisabled mismatch" )
1765+ expectedProxyHeaders := map [string ]string {
1766+ "Proxy-Authorization" : "Bearer token" ,
1767+ "Custom-Header" : "custom-value" ,
1768+ }
1769+ assert .Equal (t , expectedProxyHeaders , options .ProxyHeaders , "ProxyHeaders mismatch" )
1770+ }
1771+
1772+ func TestHasEndpoint (t * testing.T ) {
1773+ testCases := []struct {
1774+ name string
1775+ state State
1776+ expected bool
1777+ }{
1778+ {
1779+ "endpoint" ,
1780+ State {
1781+ Components : []runtime.ComponentComponentState {
1782+ {
1783+ Component : component.Component {
1784+ InputType : endpoint ,
1785+ },
1786+ },
1787+ },
1788+ },
1789+ true ,
1790+ },
1791+ {
1792+ "no endpoint" ,
1793+ State {
1794+ Components : []runtime.ComponentComponentState {
1795+ {
1796+ Component : component.Component {
1797+ InputType : "not endpoint" ,
1798+ },
1799+ },
1800+ },
1801+ },
1802+ false ,
1803+ },
1804+
1805+ {
1806+ "no component" ,
1807+ State {
1808+ Components : []runtime.ComponentComponentState {},
1809+ },
1810+ false ,
1811+ },
1812+ }
1813+
1814+ for _ , tc := range testCases {
1815+ t .Run (tc .name , func (t * testing.T ) {
1816+ c := & Coordinator {
1817+ state : tc .state ,
1818+ }
1819+
1820+ result := c .HasEndpoint ()
1821+ assert .Equal (t , tc .expected , result , "HasEndpoint result mismatch" )
1822+ })
1823+ }
1824+ }
1825+
1826+ type mockUpgradeManager struct {
1827+ upgradeErr error
1828+ }
1829+
1830+ func (m * mockUpgradeManager ) Upgradeable () bool {
1831+ return true
1832+ }
1833+
1834+ func (m * mockUpgradeManager ) Reload (cfg * config.Config ) error {
1835+ return nil
1836+ }
1837+
1838+ 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 ) {
1839+ return nil , m .upgradeErr
1840+ }
1841+
1842+ func (m * mockUpgradeManager ) Ack (ctx context.Context , acker acker.Acker ) error {
1843+ return nil
1844+ }
1845+
1846+ func (m * mockUpgradeManager ) AckAction (ctx context.Context , acker acker.Acker , action fleetapi.Action ) error {
1847+ return nil
1848+ }
1849+
1850+ func (m * mockUpgradeManager ) MarkerWatcher () upgrade.MarkerWatcher {
1851+ return nil
1852+ }
1853+
1854+ func TestCoordinator_Upgrade_InsufficientDiskSpaceError (t * testing.T ) {
1855+ log , _ := loggertest .New ("coordinator-insufficient-disk-space-test" )
1856+
1857+ mockUpgradeManager := & mockUpgradeManager {
1858+ upgradeErr : fmt .Errorf ("wrapped: %w" , upgradeErrors .ErrInsufficientDiskSpace ),
1859+ }
1860+
1861+ initialState := State {
1862+ CoordinatorState : agentclient .Healthy ,
1863+ CoordinatorMessage : "Running" ,
1864+ }
1865+
1866+ coord := & Coordinator {
1867+ state : initialState ,
1868+ logger : log ,
1869+ upgradeMgr : mockUpgradeManager ,
1870+ stateBroadcaster : broadcaster .New (initialState , 64 , 32 ),
1871+ overrideStateChan : make (chan * coordinatorOverrideState ),
1872+ upgradeDetailsChan : make (chan * details.Details ),
1873+ }
1874+
1875+ wg := sync.WaitGroup {}
1876+ wg .Add (2 )
1877+
1878+ overrideStates := []agentclient.State {}
1879+ go func () {
1880+ state1 := <- coord .overrideStateChan
1881+ overrideStates = append (overrideStates , state1 .state )
1882+
1883+ state2 := <- coord .overrideStateChan
1884+ if state2 != nil {
1885+ overrideStates = append (overrideStates , state2 .state )
1886+ }
1887+
1888+ wg .Done ()
1889+ }()
1890+
1891+ upgradeDetails := []* details.Details {}
1892+ go func () {
1893+ upgradeDetails = append (upgradeDetails , <- coord .upgradeDetailsChan )
1894+ upgradeDetails = append (upgradeDetails , <- coord .upgradeDetailsChan )
1895+ wg .Done ()
1896+ }()
1897+
1898+ err := coord .Upgrade (t .Context (), "" , "" , nil )
1899+ require .Error (t , err )
1900+ require .Equal (t , err , upgradeErrors .ErrInsufficientDiskSpace )
1901+
1902+ wg .Wait ()
1903+
1904+ require .Equal (t , []agentclient.State {agentclient .Upgrading }, overrideStates )
1905+
1906+ require .Equal (t , []* details.Details {
1907+ {
1908+ TargetVersion : "" ,
1909+ State : details .StateRequested ,
1910+ ActionID : "" ,
1911+ },
1912+ {
1913+ TargetVersion : "" ,
1914+ State : details .StateFailed ,
1915+ Metadata : details.Metadata {
1916+ FailedState : details .StateRequested ,
1917+ ErrorMsg : upgradeErrors .ErrInsufficientDiskSpace .Error (),
1918+ },
1919+ },
1920+ }, upgradeDetails )
1921+ }
1922+ >> >> >> > a7a76f6e1 (Enhancement / 5235 use disk space error to set upgrade detail in coordinator (#9392 ))
0 commit comments