in projects/aws/bottlerocket-bootstrap/pkg/utils/waiters.go [26:84]
func WaitForSystemdService(service string, timeout time.Duration) error {
fmt.Printf("Waiting for %s to come up\n", service)
conn, err := systemd.NewConnection(func() (*dbus.Conn, error) {
dbusConn, err := dbus.Dial("unix:path=/.bottlerocket/rootfs/run/dbus/system_bus_socket")
if err != nil {
return nil, errors.Wrap(err, "Error dialing br systemd")
}
err = dbusConn.Auth([]dbus.Auth{dbus.AuthExternal(strconv.Itoa(os.Getuid()))})
if err != nil {
dbusConn.Close()
return nil, errors.Wrap(err, "Error running auth on dbus connection")
}
err = dbusConn.Hello()
if err != nil {
dbusConn.Close()
return nil, errors.Wrap(err, "Error running hello handshake on dbus connection")
}
return dbusConn, nil
})
if err != nil {
return errors.Wrap(err, "Error creating systemd dbus connection")
}
fmt.Println("Created dbus connection to talk to systemd")
defer conn.Close()
// The filter function here is an inverse filter, it will filter any included units and hence nil is provided
statusChan, errChan := conn.SubscribeUnitsCustom(time.Second*1, 1, func(u1, u2 *systemd.UnitStatus) bool {
return *u1 != *u2
}, nil)
for {
select {
case unitStatus := <-statusChan:
fmt.Printf("Received status change: %+v\n", unitStatus)
if _, ok := unitStatus[service]; ok {
if unitStatus[service].ActiveState == "active" {
if strings.HasSuffix(service, ".service") {
if unitStatus[service].SubState == "running" {
fmt.Printf("%s service is active and running\n", service)
return nil
}
} else if strings.HasSuffix(service, ".target") {
if unitStatus[service].SubState == "active" {
fmt.Printf("%s service is active and running\n", service)
return nil
}
}
}
}
case err = <-errChan:
fmt.Printf("Error received while checking for unit status: %v\n", err)
return errors.Wrap(err, "Error while checking for kubelet status")
// Timeout after timeout duration
case <-time.After(timeout):
return errors.New("Timeout checking for kubelet status")
}
}
}