Skip to content

Commit

Permalink
Merge branch 'master' into patch-timeout-1
Browse files Browse the repository at this point in the history
  • Loading branch information
jm2 authored May 9, 2024
2 parents df1c456 + e92ec5e commit df96719
Show file tree
Hide file tree
Showing 13 changed files with 343 additions and 88 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/go_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jobs:
- name: Install Go
uses: actions/setup-go@v3
with:
go-version: 1.18.x
go-version: 1.22.x

- name: Check out code into the Go module directory
uses: actions/checkout@v3
Expand Down
37 changes: 17 additions & 20 deletions docs/actions.md
Original file line number Diff line number Diff line change
Expand Up @@ -288,11 +288,13 @@ Supports multiple packages via nested list structure.
* If the % character is used in ArgB, it will be replaced for the
current build branch, taken from glazier/lib/buildinfo.
* ArgC[str]: googet.exe location (Optional)
* If specified, the path to googet.exe is also used for the `-root`
flag when launching GooGet.
* If specified, the path to googet.exe is also used for the
`-root` flag when launching GooGet.
* ArgD[int]: Installation retry attemps (optional, defaults to 5)
* ArgE[int]: Installation retry sleep interval in seconds (optional,
defaults to 30)
* ArgF[bool]: Whether to uninstall the package (optional, defaults to
False)
* Arg2[str]: The second GooGet package to install (Optional)
* ...

Expand All @@ -313,10 +315,13 @@ Supports multiple packages via nested list structure.
['test_package_v1', ['http://example.com/team-unstable, http://example.co.uk/secure-unstable, https://example.jp/unstable/ -reinstall whatever'], 'C:\ProgramData\GooGet\googet.exe'],
# Package name with custom retry count of 3 and sleep interval of 60 seconds
['test_package_v1', [], , 3, 60],
['test_package_v1', [], 'C:\ProgramData\GooGet\googet.exe', 3, 60],
# Replaces '%' in custom GooGet arguments with the current build branch
['test_package_v1', ['http://example.com/team-%, http://example.co.uk/secure-%, https://example.jp/%/ -reinstall whatever'], 'C:\ProgramData\GooGet\googet.exe'],
# Remove a Googet Package with custom retry count of 3 and sleep interval of 60 seconds
['test_package_v1', [], 'C:\ProgramData\GooGet\googet.exe', 3, 60, true],
]
```

Expand Down Expand Up @@ -583,6 +588,12 @@ Reboot: [10, "Restarting to finish installing drivers."]
Reboot: [10, "Restarting to finish installing drivers.", True]
```

### RegenerateTasklist

Perform a one-shot rebuild of the Glazier task list. Note that a Registry key
created in `REG_ROOT\tasklist_regen` prevents this action from being run more
than once.

### RmDir

Remove one or more directories.
Expand Down Expand Up @@ -774,26 +785,12 @@ Process updates in MSU format. Downloads file, verifies hash, creates a
SYS_CACHE\Updates folder that is used as a temp location to extract the msu
file, and applies the update to the base image.

#### Arguments

* Format: List
* Arg1[list]: First update to apply
* ArgA[str]: Update path (can be a full HTTP(s) URL)
* ArgB[str]: Local download location.
* ArgC[str]: SHA256 hash
* Arg2[list]: Second update to apply (Optional)
* ...

#### Examples

```yaml
UpdateMSU: [
[
'@/Driver/HP/z840/win7/20160909/kb290292.msu',
'C:\Glazier_Cache\kb290292.msu',
'cd8f4222a9ba4c4493d8df208fe38cdad969514512d6f5dfd0f7cc7e1ea2c782'
]
]
Update: ['@/Driver/HP/z840/win7/20160909/kb290292.msu',
'C:\Glazier_Cache\kb290292.msu',
'cd8f4222a9ba4c4493d8df208fe38cdad969514512d6f5dfd0f7cc7e1ea2c782']
```

### Warn
Expand Down
24 changes: 17 additions & 7 deletions glazier/lib/actions/googet.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,22 @@ def Run(self):
else:
sleep = 30

if len(args) > 5:
remove = int(args[5])
else:
remove = False

try:
install = googet.GooGetInstall()
install.LaunchGooGet(pkg=args[0],
retries=retries,
sleep=sleep,
build_info=self._build_info,
path=path,
flags=flags)
install.LaunchGooGet(
pkg=args[0],
retries=retries,
sleep=sleep,
remove=remove,
build_info=self._build_info,
path=path,
flags=flags
)
except googet.Error as e:
raise ActionError('Failure executing GooGet command') from e
except IndexError as e:
Expand All @@ -64,7 +72,7 @@ def Run(self):
def Validate(self):
self._TypeValidator(self._args, list)
for args in self._args:
if not 1 <= len(args) <= 5:
if not 1 <= len(args) <= 6:
raise ValidationError(
f'Invalid GooGet args "{args}" with length of {len(args)}')
self._TypeValidator(args[0], str) # Package
Expand All @@ -76,3 +84,5 @@ def Validate(self):
self._TypeValidator(args[3], int) # Retries
if len(args) > 4:
self._TypeValidator(args[4], int) # Sleep interval
if len(args) > 5:
self._TypeValidator(args[5], bool) # Remove
47 changes: 34 additions & 13 deletions glazier/lib/actions/googet_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
DEFAULT_RETRIES = 5
SLEEP = 1
DEFAULT_SLEEP = 30
REMOVE = False


class GooGetTest(test_utils.GlazierTestCase):
Expand All @@ -45,11 +46,13 @@ def test_install_success(self, mock_install, mock_build_info):
gi.Run()
mock_install.assert_called_with(
pkg=PKG,
flags=FLAGS,
path=PATH,
retries=RETRIES,
sleep=SLEEP,
build_info=mock_build_info)
remove=REMOVE,
build_info=mock_build_info,
path=PATH,
flags=FLAGS,
)

# All args multi
action_args = [[PKG, FLAGS, PATH, RETRIES, SLEEP],
Expand All @@ -62,7 +65,9 @@ def test_install_success(self, mock_install, mock_build_info):
path=PATH,
retries=RETRIES,
sleep=SLEEP,
build_info=mock_build_info)
remove=REMOVE,
build_info=mock_build_info,
)

# No flags
action_args = [[PKG, None, PATH]]
Expand All @@ -74,7 +79,9 @@ def test_install_success(self, mock_install, mock_build_info):
flags=None,
retries=DEFAULT_RETRIES,
sleep=DEFAULT_SLEEP,
build_info=mock_build_info)
remove=REMOVE,
build_info=mock_build_info,
)

# No path
action_args = [[PKG, FLAGS]]
Expand All @@ -86,7 +93,9 @@ def test_install_success(self, mock_install, mock_build_info):
path=None,
retries=DEFAULT_RETRIES,
sleep=DEFAULT_SLEEP,
build_info=mock_build_info)
remove=REMOVE,
build_info=mock_build_info,
)

# Just package
action_args = [[PKG]]
Expand All @@ -98,7 +107,9 @@ def test_install_success(self, mock_install, mock_build_info):
flags=None,
retries=DEFAULT_RETRIES,
sleep=DEFAULT_SLEEP,
build_info=mock_build_info)
remove=REMOVE,
build_info=mock_build_info,
)

# Just package multi
action_args = [[PKG], [PKG]]
Expand All @@ -110,7 +121,9 @@ def test_install_success(self, mock_install, mock_build_info):
flags=None,
retries=DEFAULT_RETRIES,
sleep=DEFAULT_SLEEP,
build_info=mock_build_info)
remove=REMOVE,
build_info=mock_build_info,
)

# Package custom retry count and sleep interval
action_args = [[PKG, None, None, RETRIES, SLEEP]]
Expand All @@ -122,7 +135,9 @@ def test_install_success(self, mock_install, mock_build_info):
flags=None,
retries=RETRIES,
sleep=SLEEP,
build_info=mock_build_info)
remove=REMOVE,
build_info=mock_build_info,
)

@parameterized.named_parameters(
('_googeterror', [[PKG, FLAGS, PATH, RETRIES, SLEEP]]),
Expand All @@ -137,9 +152,15 @@ def test_install_error(self, action_args, mock_install, mock_build_info):
gi.Run()

@parameterized.named_parameters(
('_valid_calls', [[PKG, FLAGS, PATH, RETRIES, SLEEP]], None),
('_valid_calls_multi', [[PKG, FLAGS, PATH, RETRIES, SLEEP],
[PKG, FLAGS, PATH, RETRIES, SLEEP]], None),
('_valid_calls', [[PKG, FLAGS, PATH, RETRIES, SLEEP, REMOVE]], None),
(
'_valid_calls_multi',
[
[PKG, FLAGS, PATH, RETRIES, SLEEP, REMOVE],
[PKG, FLAGS, PATH, RETRIES, SLEEP, REMOVE],
],
None,
),
)
def test_validation_success(self, action_args, build_info):
g = googet.GooGetInstall(action_args, build_info)
Expand All @@ -149,7 +170,7 @@ def test_validation_success(self, action_args, build_info):
('_list_not_passed', ['String'], None),
('_too_few_args', [[]], None),
('_too_many_args', [[PKG, FLAGS, PATH, 'abc']], None),
('_type_error', [PKG, FLAGS, PATH, RETRIES, SLEEP, 1], None),
('_type_error', [PKG, FLAGS, PATH, RETRIES, SLEEP, REMOVE, 1], None),
)
def test_validation_error(self, action_args, build_info):
g = googet.GooGetInstall(action_args, build_info)
Expand Down
66 changes: 66 additions & 0 deletions glazier/lib/actions/tasklist.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Copyright 2016 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Actions to regenerate Glazier tasklist."""

import os

from glazier.lib import constants
from glazier.lib import flags
from glazier.lib import logs
from glazier.lib import registry
from glazier.lib import winpe
from glazier.lib.actions import base
from glazier.lib.config import builder

from glazier.lib import buildinfo


logging = logs.logging


class RegenerateTasklist(base.BaseAction):
"""Regenerate Glazier tasklist."""

def __init__(self):
self._build_info = buildinfo.BuildInfo()

def _PurgeTaskList(self):
"""Determines the location of the task list and erases it for regeneration."""
location = constants.SYS_TASK_LIST
if winpe.check_winpe():
location = constants.WINPE_TASK_LIST
logging.info('Using task list at %s', location)
if os.path.exists(location):
logging.info('Purging old task list.')
try:
os.remove(location)
except OSError as e:
raise base.ActionError() from e
return location

def Run(self):
regen_run = registry.get_value('tasklist_regen', path=constants.REG_ROOT)
if regen_run != 'True':
task_list = self._PurgeTaskList()
root_path = flags.CONFIG_ROOT_PATH.value or '/'
try:
b = builder.ConfigBuilder(self._build_info)
b.Start(out_file=task_list, in_path=root_path)
except builder.ConfigBuilderError as e:
raise base.ActionError() from e
registry.set_value('tasklist_regen', 'True', path=constants.REG_ROOT)

def Validate(self):
self._ListOfStringsValidator(self._args)
56 changes: 56 additions & 0 deletions glazier/lib/actions/tasklist_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Copyright 2016 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Tests for glazier.lib.actions.tasklist."""

from unittest import mock

from absl.testing import absltest
from glazier.lib import test_utils
from glazier.lib import winpe
from glazier.lib.actions import base
from glazier.lib.actions import tasklist


class TasklistTest(test_utils.GlazierTestCase):

@mock.patch.object(tasklist, 'logs', autospec=True)
def setUp(self, logs):
super().setUp()
self.tasklist = tasklist.RegenerateTasklist()
tasklist.logging = logs.logging

@mock.patch.object(winpe, 'check_winpe', autospec=True)
def test_setup_task_list_host(self, mock_check_winpe):
tasklist_location = tasklist.constants.SYS_TASK_LIST
mock_check_winpe.return_value = False
self.assertEqual(self.tasklist._PurgeTaskList(), tasklist_location)

@mock.patch.object(winpe, 'check_winpe', autospec=True)
def test_setup_task_list_winpe(self, mock_check_winpe):
self.patch_constant_file_path(tasklist.constants, 'WINPE_TASK_LIST')
mock_check_winpe.return_value = True
tasklist_location = tasklist.constants.WINPE_TASK_LIST
self.assertEqual(self.tasklist._PurgeTaskList(), tasklist_location)

@mock.patch.object(tasklist, 'os', autospec=True)
def test_setup_task_list_error(self, mock_os):
self.patch_constant_file_path(tasklist.constants, 'SYS_TASK_LIST')
mock_os.remove.side_effect = OSError
with self.assertRaises(base.ActionError):
self.tasklist._PurgeTaskList()


if __name__ == '__main__':
absltest.main()
Loading

0 comments on commit df96719

Please sign in to comment.