func WaitForSystemdService()

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")
		}
	}
}