Repository: opendatacube/datacube-core

Issue:
dc.list_products() is not showing grid_spec used in dc.load()
### Expected behaviour

```
dc = datacube.Datacube()
dc.list_products()
```

show all `output_resolution` and `output_crs` used in load_hint when calling `dc.load()`

```
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
/tmp/ipykernel_122/705763191.py in <module>
----> 1 ds = dc.load(product="ga_ls_tc_pc_cyear_3", 
      2              **query_params,
      3              **load_params)

/env/lib/python3.8/site-packages/datacube/api/core.py in load(self, product, measurements, output_crs, resolution, resampling, skip_broken_datasets, dask_chunks, like, fuse_func, align, datasets, dataset_predicate, progress_cbk, **query)
    414                 return xarray.Dataset()
    415 
--> 416         geobox = output_geobox(like=like, output_crs=output_crs, resolution=resolution, align=align,
    417                                grid_spec=datacube_product.grid_spec,
    418                                load_hints=datacube_product.load_hints(),

/env/lib/python3.8/site-packages/datacube/api/core.py in output_geobox(like, output_crs, resolution, align, grid_spec, load_hints, datasets, geopolygon, **query)
    855         align = align or grid_spec.alignment
    856     else:
--> 857         raise ValueError("Product has no default CRS. Must specify 'output_crs' and 'resolution'")
    858 
    859     # Try figuring out bounds

ValueError: Product has no default CRS. Must specify 'output_crs' and 'resolution'
```
due to it does not have grid_spec, below is one product with `grid_spec`

```
l8_gm = dc.index.products.get_by_name("ga_ls8c_nbart_gm_cyear_3")
l8_gm.grid_spec
GridSpec(crs=EPSG:3577, tile_size=(3200.0, 3200.0), resolution=(-30, 30))
```


Discussion:

Resolving patch:
diff --git a/datacube/api/core.py b/datacube/api/core.py
--- a/datacube/api/core.py
+++ b/datacube/api/core.py
@@ -98,8 +98,8 @@ def list_products(self, with_pandas=True, dataset_count=False):
             'name'
             'description'
             'license'
-            'default_crs'
-            'default_resolution'
+            'default_crs' or 'grid_spec.crs'
+            'default_resolution' or 'grid_spec.crs'
             'dataset_count' (optional)
 
         :param bool with_pandas:
@@ -121,8 +121,16 @@ def list_products(self, with_pandas=True, dataset_count=False):
             'default_crs',
             'default_resolution',
         ]
-        rows = [[getattr(pr, col, None) for col in cols]
-                for pr in self.index.products.get_all()]
+        rows = [[
+            getattr(pr, col, None)
+            # if 'default_crs' and 'default_resolution' are not None
+            # return 'default_crs' and 'default_resolution'
+            if getattr(pr, col, None) and 'default' not in col
+            # else try 'grid_spec.crs' and 'grid_spec.resolution'
+            # as per output_geobox() handling logic
+            else getattr(pr.grid_spec, col.replace('default_', ''), None)
+            for col in cols]
+            for pr in self.index.products.get_all()]
 
         # Optionally compute dataset count for each product and add to row/cols
         # Product lists are sorted by product name to ensure 1:1 match
@@ -870,7 +878,10 @@ def output_geobox(like=None, output_crs=None, resolution=None, align=None,
             resolution = grid_spec.resolution
         align = align or grid_spec.alignment
     else:
-        raise ValueError("Product has no default CRS. Must specify 'output_crs' and 'resolution'")
+        raise ValueError(
+            "Product has no default CRS. \n"
+            "Must specify 'output_crs' and 'resolution'"
+        )
 
     # Try figuring out bounds
     #  1. Explicitly defined with geopolygon


Test patch: