Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resolve search sections that match several devices #1691

Merged
merged 7 commits into from
Oct 24, 2024

Conversation

ancorgs
Copy link
Contributor

@ancorgs ancorgs commented Oct 23, 2024

Problem

The search functionality described at auto_storage.md is pretty powerful. But the current implementation only allows to:

  • search by name
  • return 0 or 1 devices per search

Solution

This implements several parts of the missing functionality, like:

  • Ability to match more than one device per search section
  • Limit the number of matches by using max.

This pull request does not add the ability to use other conditions or matching order beyond name. So it's only possible to search either for a device with a given name, either for all the devices sorted by name. The syntax for the latter would be this (a search with no conditions):

{ "search": {} }

For readability, the following alternative syntax is also introduced at this pull request:

{ "search": "*" }

The new default for drive entries (if omitted) becomes:

{ "search": { "max": 1 } }

If several devices match with a given search section, the corresponding configuration containing the search is replicated as many times as needed. Eg. in a system with two disks, the following config...

{
  "storage": {
    "drives": [
      { "search": "*" }
    ]
  }
}

...is expanded into:

{
  "storage": {
    "drives": [
      { "search": "*" },
      { "search": "*" }
    ]
  }
}

This also makes sure everything keeps working when an alias is used together with a search that matches several devices (so all the resulting config objects share the same alias).

Testing

  • Adapted existing unit tests and added a new ones regarding the search functionality
  • Added a new unit test to check that resolving a config into several ones (potentially with a shared alias) works as expected.

@ancorgs ancorgs force-pushed the expand_search branch 2 times, most recently from 266cd14 to 900cb7a Compare October 23, 2024 10:35
@coveralls
Copy link

coveralls commented Oct 23, 2024

Pull Request Test Coverage Report for Build 11480395585

Details

  • 51 of 51 (100.0%) changed or added relevant lines in 7 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage increased (+0.05%) to 71.446%

Totals Coverage Status
Change from base Build 11460749266: 0.05%
Covered Lines: 16927
Relevant Lines: 23692

💛 - Coveralls

@ancorgs ancorgs marked this pull request as ready for review October 23, 2024 13:03
Copy link
Contributor

@joseivanlopez joseivanlopez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some notes we already talked about:

  • Adapt schema to include max in the search section.
  • Adapt schema to include and document "*" const as possible value for search.
  • Extend conversion to JSON to include max in search.

service/lib/agama/storage/configs/encryption.rb Outdated Show resolved Hide resolved
#
# Needed when a search returns multiple devices and the configuration needs to be replicated
# for each one.
def copy
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note for myself: use Copyable mixing introduced by #1692.

service/lib/agama/storage/configs/search.rb Show resolved Hide resolved
@ancorgs ancorgs force-pushed the expand_search branch 3 times, most recently from c4e4269 to bf4cb19 Compare October 24, 2024 08:53
@ancorgs
Copy link
Contributor Author

ancorgs commented Oct 24, 2024

@joseivanlopez I updated the PR (using force push, sorry) to address all concerns. Please re-review

Copy link
Contributor

@joseivanlopez joseivanlopez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some comments. Feel free to ignore the NPs.

Changelog entry is missing.

# @see Base#convert
def convert
converted = super
return SEARCH_ANYTHING_STRING if converted.is_a?(Hash) && anything?(converted)
Copy link
Contributor

@joseivanlopez joseivanlopez Oct 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure yet if we should generate wildcard. I think this is the only case in which we do it. Let's keep it for now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was not sure either. Our exporting is a bit weird in some aspects (like always adding the device name for found devices). I guess we will have to reconsider all that soon.

Copy link
Contributor

@joseivanlopez joseivanlopez Oct 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would say that adding the device name is kind of expected for a solved config. I mean, independently of the initial conditions, I would expect the solved config should be a search by name. For example:

{ 
  search: { 
    condition: { size: { bigger: "10 GiB" } }
  }
}

Resolves to:

{ 
  search: "/dev/vdc" 
}

But of course, we can reconsider it.


value = search_json[:ifNotFound]
return unless value
# @return [String]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NP: I think we can follow the same implementation pattern as the rest of conversions:

          # @see Base#conversions
          # @return [Hash]
          def conversions
            {
              name:         convert_name,
              max:          search_json[:max],
              if_not_found: convert_not_found
            }
          end

          # @return [String, nil]
          def convert_name
            return if search_json == SEARCH_ANYTHING_STRING
            return search_json if search_json.is_a?(String)

            search_json.dig(:condition, :name)
          end

          # @return [Symbol, nil]
          def convert_not_found
            return :skip if search_json == SEARCH_ANYTHING_STRING
            return if search_json.is_a?(String)
            
            search_json[:ifNotFound]&.to_sym          
          end

Copy link
Contributor Author

@ancorgs ancorgs Oct 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find that much harder to follow.

We typically handle a hash except an special case in which a string can be used as shortcut.

With the implementation in this PR, that special case is handled at its own method.

With the implementation you suggest, the management is spread over several methods, all of them with its own exception for the string case. And the more attributes we add, the more methods we have with a dedicated if at the beginning. I don't see the point.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we see it differently. In the conversions I prefer to focus on each attribute and assign a value according to the value of the search_json. But it is a NP anyway, so let keep your implementation.

Copy link
Contributor

@joseivanlopez joseivanlopez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

expect(disk.partitions.size).to eq 1
end

it "register a warning about non-existent partitions" do
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW, I think we should reconsider this behavior. I don't think it's worth a warning. It can generate noise in many situations.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the record: we agreed it makes no sense and it will be changed in a subsequent pull request.

@ancorgs ancorgs merged commit 825ad0c into agama-project:master Oct 24, 2024
4 checks passed
@imobachgs imobachgs mentioned this pull request Jan 10, 2025
imobachgs added a commit that referenced this pull request Jan 13, 2025
Update to release version 11.

* #1495
* #1564
* #1617
* #1618
* #1625
* #1626
* #1627
* #1628
* #1630
* #1631
* #1632
* #1633
* #1634
* #1635
* #1636
* #1639
* #1640
* #1641
* #1642
* #1643
* #1644
* #1645
* #1646
* #1647
* #1648
* #1649
* #1650
* #1651
* #1652
* #1654
* #1655
* #1656
* #1657
* #1660
* #1663
* #1666
* #1667
* #1668
* #1670
* #1671
* #1673
* #1674
* #1675
* #1676
* #1677
* #1681
* #1682
* #1683
* #1684
* #1687
* #1688
* #1689
* #1690
* #1691
* #1692
* #1693
* #1694
* #1695
* #1696
* #1698
* #1699
* #1702
* #1703
* #1704
* #1705
* #1707
* #1708
* #1709
* #1710
* #1711
* #1712
* #1713
* #1714
* #1715
* #1716
* #1717
* #1718
* #1720
* #1721
* #1722
* #1723
* #1727
* #1728
* #1729
* #1731
* #1732
* #1733
* #1734
* #1735
* #1736
* #1737
* #1740
* #1741
* #1743
* #1744
* #1745
* #1746
* #1751
* #1753
* #1754
* #1755
* #1757
* #1762
* #1763
* #1764
* #1765
* #1766
* #1767
* #1769
* #1771
* #1772
* #1773
* #1774
* #1777
* #1778
* #1785
* #1786
* #1787
* #1788
* #1789
* #1790
* #1791
* #1792
* #1793
* #1794
* #1795
* #1796
* #1797
* #1798
* #1799
* #1800
* #1802
* #1803
* #1804
* #1805
* #1807
* #1808
* #1809
* #1810
* #1811
* #1812
* #1814
* #1815
* #1821
* #1822
* #1823
* #1824
* #1825
* #1826
* #1827
* #1828
* #1830
* #1831
* #1832
* #1833
* #1834
* #1835
* #1836
* #1837
* #1838
* #1839
* #1840
* #1841
* #1842
* #1843
* #1844
* #1845
* #1847
* #1848
* #1849
* #1850
* #1851
* #1854
* #1855
* #1856
* #1857
* #1860
* #1861
* #1863
* #1864
* #1865
* #1866
* #1867
* #1871
* #1872
* #1873
* #1875
* #1876
* #1877
* #1878
* #1880
* #1881
* #1882
* #1883
* #1884
* #1885
* #1886
* #1888
* #1889
* #1890
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants