• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

k8snetworkplumbingwg / sriov-network-operator / 8467233545

28 Mar 2024 12:26PM UTC coverage: 38.344% (+0.7%) from 37.675%
8467233545

push

github

web-flow
Merge pull request #643 from ykulazhenkov/pr-turn-on-switchdev

[switchdev 9/9] Enable new switchdev implementation

189 of 289 new or added lines in 9 files covered. (65.4%)

26 existing lines in 8 files now uncovered.

4798 of 12513 relevant lines covered (38.34%)

0.42 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

17.04
/pkg/host/internal/service/service.go
1
package service
2

3
import (
4
        "fmt"
5
        "io"
6
        "os"
7
        "path"
8
        "path/filepath"
9
        "strings"
10

11
        "github.com/coreos/go-systemd/v22/unit"
12
        "gopkg.in/yaml.v3"
13
        "sigs.k8s.io/controller-runtime/pkg/log"
14

15
        "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts"
16
        "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/types"
17
        "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/utils"
18
)
19

20
// TODO: handle this to support unit-tests
21
const systemdDir = "/usr/lib/systemd/system/"
22

23
type service struct {
24
        utilsHelper utils.CmdInterface
25
}
26

27
func New(utilsHelper utils.CmdInterface) types.ServiceInterface {
1✔
28
        return &service{utilsHelper: utilsHelper}
1✔
29
}
1✔
30

31
// ServiceInjectionManifestFile service injection manifest file structure
32
type ServiceInjectionManifestFile struct {
33
        Name    string
34
        Dropins []struct {
35
                Contents string
36
        }
37
}
38

39
// IsServiceExist check if service unit exist
40
func (s *service) IsServiceExist(servicePath string) (bool, error) {
×
41
        _, err := os.Stat(path.Join(consts.Chroot, servicePath))
×
42
        if err != nil {
×
43
                if os.IsNotExist(err) {
×
44
                        return false, nil
×
45
                }
×
46
                return false, err
×
47
        }
48

49
        return true, nil
×
50
}
51

52
// IsServiceEnabled check if service exist and enabled
53
func (s *service) IsServiceEnabled(servicePath string) (bool, error) {
×
54
        exist, err := s.IsServiceExist(servicePath)
×
55
        if err != nil || !exist {
×
56
                return false, err
×
57
        }
×
58
        serviceName := filepath.Base(servicePath)
×
59
        // Change root dir
×
60
        exit, err := s.utilsHelper.Chroot(consts.Chroot)
×
61
        if err != nil {
×
62
                return false, err
×
63
        }
×
64
        defer exit()
×
65

×
66
        // TODO: add check for the output and logs
×
67
        _, _, err = s.utilsHelper.RunCommand("systemctl", "is-enabled", serviceName)
×
68
        return err == nil, nil
×
69
}
70

71
// ReadService read service from given path
72
func (s *service) ReadService(servicePath string) (*types.Service, error) {
×
73
        data, err := os.ReadFile(path.Join(consts.Chroot, servicePath))
×
74
        if err != nil {
×
75
                return nil, err
×
76
        }
×
77

78
        return &types.Service{
×
79
                Name:    filepath.Base(servicePath),
×
80
                Path:    servicePath,
×
81
                Content: string(data),
×
82
        }, nil
×
83
}
84

85
// EnableService creates service file and enables it with systemctl enable
86
func (s *service) EnableService(service *types.Service) error {
×
87
        // Write service file
×
88
        err := os.WriteFile(path.Join(consts.Chroot, service.Path), []byte(service.Content), 0644)
×
89
        if err != nil {
×
90
                return err
×
91
        }
×
92

93
        // Change root dir
94
        exit, err := s.utilsHelper.Chroot(consts.Chroot)
×
95
        if err != nil {
×
96
                return err
×
97
        }
×
98
        defer exit()
×
99

×
100
        // Enable service
×
101
        _, _, err = s.utilsHelper.RunCommand("systemctl", "enable", service.Name)
×
102
        return err
×
103
}
104

105
// CompareServices returns true if serviceA needs update(doesn't contain all fields from service B)
106
func (s *service) CompareServices(serviceA, serviceB *types.Service) (bool, error) {
×
107
        optsA, err := unit.Deserialize(strings.NewReader(serviceA.Content))
×
108
        if err != nil {
×
109
                return false, err
×
110
        }
×
111
        optsB, err := unit.Deserialize(strings.NewReader(serviceB.Content))
×
112
        if err != nil {
×
113
                return false, err
×
114
        }
×
115

116
OUTER:
×
117
        for _, optB := range optsB {
×
118
                for _, optA := range optsA {
×
119
                        if optA.Match(optB) {
×
120
                                continue OUTER
×
121
                        }
122
                }
123
                log.Log.V(2).Info("CompareServices", "ServiceA", optsA, "ServiceB", *optB)
×
124
                return true, nil
×
125
        }
126

127
        return false, nil
×
128
}
129

130
// ReadServiceInjectionManifestFile reads service injection file
131
func (s *service) ReadServiceInjectionManifestFile(path string) (*types.Service, error) {
1✔
132
        data, err := os.ReadFile(path)
1✔
133
        if err != nil {
1✔
134
                return nil, err
×
135
        }
×
136

137
        var serviceContent ServiceInjectionManifestFile
1✔
138
        if err := yaml.Unmarshal(data, &serviceContent); err != nil {
1✔
139
                return nil, err
×
140
        }
×
141

142
        return &types.Service{
1✔
143
                Name:    serviceContent.Name,
1✔
144
                Path:    systemdDir + serviceContent.Name,
1✔
145
                Content: serviceContent.Dropins[0].Contents,
1✔
146
        }, nil
1✔
147
}
148

149
// ReadServiceManifestFile reads service file
150
func (s *service) ReadServiceManifestFile(path string) (*types.Service, error) {
1✔
151
        data, err := os.ReadFile(path)
1✔
152
        if err != nil {
1✔
153
                return nil, err
×
154
        }
×
155

156
        var serviceFile *types.ServiceManifestFile
1✔
157
        if err := yaml.Unmarshal(data, &serviceFile); err != nil {
1✔
158
                return nil, err
×
159
        }
×
160

161
        return &types.Service{
1✔
162
                Name:    serviceFile.Name,
1✔
163
                Path:    "/etc/systemd/system/" + serviceFile.Name,
1✔
164
                Content: serviceFile.Contents,
1✔
165
        }, nil
1✔
166
}
167

UNCOV
168
func (s *service) UpdateSystemService(serviceObj *types.Service) error {
×
UNCOV
169
        systemService, err := s.ReadService(serviceObj.Path)
×
170
        if err != nil {
×
171
                return err
×
172
        }
×
173
        if systemService == nil {
×
174
                // Invalid case to reach here
×
175
                return fmt.Errorf("can't update non-existing service %q", serviceObj.Name)
×
176
        }
×
177
        serviceOptions, err := unit.Deserialize(strings.NewReader(serviceObj.Content))
×
178
        if err != nil {
×
179
                return err
×
180
        }
×
181
        updatedService, err := appendToService(systemService, serviceOptions...)
×
182
        if err != nil {
×
183
                return err
×
184
        }
×
185

186
        return s.EnableService(updatedService)
×
187
}
188

189
// appendToService appends given fields to service
190
func appendToService(service *types.Service, options ...*unit.UnitOption) (*types.Service, error) {
×
191
        serviceOptions, err := unit.Deserialize(strings.NewReader(service.Content))
×
192
        if err != nil {
×
193
                return nil, err
×
194
        }
×
195

196
OUTER:
×
197
        for _, appendOpt := range options {
×
198
                for _, opt := range serviceOptions {
×
199
                        if opt.Match(appendOpt) {
×
200
                                continue OUTER
×
201
                        }
202
                }
203
                serviceOptions = append(serviceOptions, appendOpt)
×
204
        }
205

206
        data, err := io.ReadAll(unit.Serialize(serviceOptions))
×
207
        if err != nil {
×
208
                return nil, err
×
209
        }
×
210

211
        return &types.Service{
×
212
                Name:    service.Name,
×
213
                Path:    service.Path,
×
214
                Content: string(data),
×
215
        }, nil
×
216
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc